cqm-models 1.0.3 → 1.1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.eslintrc.json +10 -2
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -4
- data/.rubocop.yml +3 -0
- data/.travis.yml +31 -1
- data/README.md +59 -2
- data/app/assets/javascripts/AdverseEvent.js +16 -7
- data/app/assets/javascripts/AllDataElements.js +6 -6
- data/app/assets/javascripts/AllergyIntolerance.js +16 -7
- data/app/assets/javascripts/AssessmentOrder.js +15 -6
- data/app/assets/javascripts/AssessmentPerformed.js +16 -7
- data/app/assets/javascripts/AssessmentRecommended.js +16 -7
- data/app/assets/javascripts/CareGoal.js +16 -7
- data/app/assets/javascripts/CommunicationPerformed.js +15 -6
- data/app/assets/javascripts/DeviceApplied.js +16 -7
- data/app/assets/javascripts/DeviceOrder.js +16 -7
- data/app/assets/javascripts/DeviceRecommended.js +16 -7
- data/app/assets/javascripts/Diagnosis.js +16 -7
- data/app/assets/javascripts/DiagnosticStudyOrder.js +16 -7
- data/app/assets/javascripts/DiagnosticStudyPerformed.js +16 -7
- data/app/assets/javascripts/DiagnosticStudyRecommended.js +16 -7
- data/app/assets/javascripts/EncounterOrder.js +16 -7
- data/app/assets/javascripts/EncounterPerformed.js +16 -7
- data/app/assets/javascripts/EncounterRecommended.js +16 -7
- data/app/assets/javascripts/FamilyHistory.js +16 -7
- data/app/assets/javascripts/Id.js +7 -3
- data/app/assets/javascripts/ImmunizationAdministered.js +16 -7
- data/app/assets/javascripts/ImmunizationOrder.js +16 -7
- data/app/assets/javascripts/IndividualResult.js +7 -2
- data/app/assets/javascripts/InterventionOrder.js +16 -7
- data/app/assets/javascripts/InterventionPerformed.js +16 -7
- data/app/assets/javascripts/InterventionRecommended.js +16 -7
- data/app/assets/javascripts/LaboratoryTestOrder.js +16 -7
- data/app/assets/javascripts/LaboratoryTestPerformed.js +16 -7
- data/app/assets/javascripts/LaboratoryTestRecommended.js +16 -7
- data/app/assets/javascripts/MedicationActive.js +16 -7
- data/app/assets/javascripts/MedicationAdministered.js +16 -7
- data/app/assets/javascripts/MedicationDischarge.js +16 -7
- data/app/assets/javascripts/MedicationDispensed.js +16 -7
- data/app/assets/javascripts/MedicationOrder.js +16 -7
- data/app/assets/javascripts/Participation.js +15 -6
- data/app/assets/javascripts/PatientCareExperience.js +16 -7
- data/app/assets/javascripts/PatientCharacteristic.js +16 -7
- data/app/assets/javascripts/PatientCharacteristicBirthdate.js +16 -7
- data/app/assets/javascripts/PatientCharacteristicClinicalTrialParticipant.js +16 -7
- data/app/assets/javascripts/PatientCharacteristicEthnicity.js +16 -7
- data/app/assets/javascripts/PatientCharacteristicExpired.js +16 -7
- data/app/assets/javascripts/PatientCharacteristicPayer.js +16 -7
- data/app/assets/javascripts/PatientCharacteristicRace.js +16 -7
- data/app/assets/javascripts/PatientCharacteristicSex.js +16 -7
- data/app/assets/javascripts/PhysicalExamOrder.js +16 -7
- data/app/assets/javascripts/PhysicalExamPerformed.js +16 -7
- data/app/assets/javascripts/PhysicalExamRecommended.js +16 -7
- data/app/assets/javascripts/ProcedureOrder.js +16 -7
- data/app/assets/javascripts/ProcedurePerformed.js +16 -7
- data/app/assets/javascripts/ProcedureRecommended.js +16 -7
- data/app/assets/javascripts/ProviderCareExperience.js +16 -7
- data/app/assets/javascripts/ProviderCharacteristic.js +16 -7
- data/app/assets/javascripts/QDMPatient.js +262 -0
- data/app/assets/javascripts/Result.js +7 -2
- data/app/assets/javascripts/ResultComponent.js +14 -6
- data/app/assets/javascripts/SubstanceAdministered.js +16 -7
- data/app/assets/javascripts/SubstanceOrder.js +16 -7
- data/app/assets/javascripts/SubstanceRecommended.js +16 -7
- data/app/assets/javascripts/Symptom.js +16 -7
- data/app/assets/javascripts/attributes/Component.js +30 -0
- data/app/assets/javascripts/attributes/FacilityLocation.js +30 -0
- data/app/assets/javascripts/basetypes/Any.js +1 -1
- data/app/assets/javascripts/basetypes/Code.js +1 -1
- data/app/assets/javascripts/basetypes/DataElement.js +2 -1
- data/app/assets/javascripts/basetypes/DateTime.js +5 -1
- data/app/assets/javascripts/basetypes/Interval.js +1 -1
- data/app/assets/javascripts/basetypes/Quantity.js +1 -1
- data/app/assets/javascripts/basetypes/Ratio.js +1 -1
- data/app/assets/javascripts/browser.js +3 -0
- data/app/assets/javascripts/cqm/AllCQMModels.js +24 -0
- data/app/assets/javascripts/cqm/CQLLibrary.js +32 -0
- data/app/assets/javascripts/cqm/CQLStatementDependency.js +28 -0
- data/app/assets/javascripts/cqm/Concept.js +17 -0
- data/app/assets/javascripts/cqm/Measure.js +108 -0
- data/app/assets/javascripts/{MeasurePackage.js → cqm/MeasurePackage.js} +9 -3
- data/app/assets/javascripts/cqm/Patient.js +38 -0
- data/app/assets/javascripts/cqm/PopulationSet.js +88 -0
- data/app/assets/javascripts/cqm/Provider.js +44 -0
- data/app/assets/javascripts/cqm/ValueSet.js +26 -0
- data/app/assets/javascripts/index.js +18 -8
- data/app/models/{qdm/tacoma → cqm}/concept.rb +4 -4
- data/app/models/cqm/cql_library.rb +22 -0
- data/app/models/cqm/cql_statement_dependency.rb +24 -0
- data/app/models/cqm/measure.rb +105 -0
- data/app/models/{qdm/tacoma → cqm}/measure_package.rb +2 -2
- data/app/models/cqm/patient.rb +20 -0
- data/app/models/cqm/population_set.rb +86 -0
- data/app/models/cqm/provider.rb +110 -0
- data/app/models/cqm/valueset.rb +15 -0
- data/app/models/hqmfOid_to_datatype_map.json +55 -0
- data/app/models/model_finder.rb +12 -0
- data/app/models/models.rb +18 -6
- data/app/models/qdm/adverse_event.rb +3 -2
- data/app/models/qdm/allergy_intolerance.rb +2 -1
- data/app/models/qdm/assessment_order.rb +1 -0
- data/app/models/qdm/assessment_performed.rb +2 -1
- data/app/models/qdm/assessment_recommended.rb +2 -1
- data/app/models/qdm/attributes/attribute.rb +63 -0
- data/app/models/qdm/{component.rb → attributes/component.rb} +1 -1
- data/app/models/qdm/{facility_location.rb → attributes/facility_location.rb} +1 -1
- data/app/models/qdm/basetypes/data_element.rb +21 -6
- data/app/models/qdm/basetypes/interval.rb +2 -1
- data/app/models/qdm/care_goal.rb +2 -1
- data/app/models/qdm/communication_performed.rb +1 -0
- data/app/models/qdm/device_applied.rb +2 -1
- data/app/models/qdm/device_order.rb +2 -1
- data/app/models/qdm/device_recommended.rb +2 -1
- data/app/models/qdm/diagnosis.rb +2 -1
- data/app/models/qdm/diagnostic_study_order.rb +2 -1
- data/app/models/qdm/diagnostic_study_performed.rb +3 -2
- data/app/models/qdm/diagnostic_study_recommended.rb +2 -1
- data/app/models/qdm/encounter_order.rb +3 -2
- data/app/models/qdm/encounter_performed.rb +2 -1
- data/app/models/qdm/encounter_recommended.rb +3 -2
- data/app/models/qdm/family_history.rb +2 -1
- data/app/models/qdm/immunization_administered.rb +2 -1
- data/app/models/qdm/immunization_order.rb +2 -1
- data/app/models/qdm/intervention_order.rb +2 -1
- data/app/models/qdm/intervention_performed.rb +2 -1
- data/app/models/qdm/intervention_recommended.rb +2 -1
- data/app/models/qdm/laboratory_test_order.rb +2 -1
- data/app/models/qdm/laboratory_test_performed.rb +2 -1
- data/app/models/qdm/laboratory_test_recommended.rb +2 -1
- data/app/models/qdm/medication_active.rb +2 -1
- data/app/models/qdm/medication_administered.rb +2 -1
- data/app/models/qdm/medication_discharge.rb +2 -1
- data/app/models/qdm/medication_dispensed.rb +4 -3
- data/app/models/qdm/medication_order.rb +3 -2
- data/app/models/qdm/participation.rb +1 -0
- data/app/models/qdm/patient.rb +7 -4
- data/app/models/qdm/patient_care_experience.rb +2 -1
- data/app/models/qdm/patient_characteristic.rb +2 -1
- data/app/models/qdm/patient_characteristic_birthdate.rb +2 -1
- data/app/models/qdm/patient_characteristic_clinical_trial_participant.rb +2 -1
- data/app/models/qdm/patient_characteristic_ethnicity.rb +2 -1
- data/app/models/qdm/patient_characteristic_expired.rb +2 -1
- data/app/models/qdm/patient_characteristic_payer.rb +2 -1
- data/app/models/qdm/patient_characteristic_race.rb +2 -1
- data/app/models/qdm/patient_characteristic_sex.rb +2 -1
- data/app/models/qdm/physical_exam_order.rb +2 -1
- data/app/models/qdm/physical_exam_performed.rb +2 -1
- data/app/models/qdm/physical_exam_recommended.rb +2 -1
- data/app/models/qdm/procedure_order.rb +2 -1
- data/app/models/qdm/procedure_performed.rb +2 -1
- data/app/models/qdm/procedure_recommended.rb +2 -1
- data/app/models/qdm/provider_care_experience.rb +2 -1
- data/app/models/qdm/provider_characteristic.rb +2 -1
- data/app/models/qdm/substance_administered.rb +2 -1
- data/app/models/qdm/substance_order.rb +2 -1
- data/app/models/qdm/substance_recommended.rb +2 -1
- data/app/models/qdm/symptom.rb +2 -1
- data/bin/build_cql_execution.sh +8 -0
- data/bin/validate_browser.sh +17 -0
- data/bin/validate_generator.sh +12 -0
- data/cqm-models.gemspec +5 -2
- data/data/oids_qdm_5.4.json +321 -0
- data/data/{oids.json → oids_unversioned.json} +0 -0
- data/dist/browser.js +102937 -0
- data/dist/index.js +36637 -36540
- data/lib/generate_models.rb +89 -93
- data/lib/generate_patients.rb +125 -0
- data/lib/generate_types.rb +64 -0
- data/lib/generators/custom_mongo/model.rb.tt +20 -0
- data/lib/generators/custom_mongo/model_generator.rb +34 -0
- data/notice.md +9 -0
- data/package.json +12 -6
- data/templates/id_template.js.erb +8 -3
- data/templates/index_template.js.erb +18 -8
- data/templates/models_template.rb.erb +20 -4
- data/templates/mongoose_template.js.erb +23 -15
- data/templates/patient_extension.rb.erb +7 -4
- data/templates/patient_template.js.erb +88 -87
- data/yarn.lock +552 -347
- metadata +86 -19
- data/app/assets/javascripts/Component.js +0 -26
- data/app/assets/javascripts/Concept.js +0 -14
- data/app/assets/javascripts/FacilityLocation.js +0 -26
- data/app/assets/javascripts/Measure.js +0 -78
- data/app/assets/javascripts/Patient.js +0 -262
- data/app/assets/javascripts/ValueSet.js +0 -30
- data/app/models/qdm/tacoma/measure.rb +0 -174
- data/app/models/qdm/tacoma/valueset.rb +0 -68
@@ -1,30 +0,0 @@
|
|
1
|
-
const mongoose = require('mongoose');
|
2
|
-
const Concept = require('./Concept.js');
|
3
|
-
|
4
|
-
const [String, Mixed, ObjectId] = [
|
5
|
-
mongoose.Schema.Types.String,
|
6
|
-
mongoose.Schema.Types.Mixed,
|
7
|
-
mongoose.Schema.Types.ObjectId,
|
8
|
-
];
|
9
|
-
|
10
|
-
const ValueSetSchema = mongoose.Schema(
|
11
|
-
{
|
12
|
-
oid: String,
|
13
|
-
display_name: String,
|
14
|
-
version: String,
|
15
|
-
categories: Mixed,
|
16
|
-
|
17
|
-
concepts: [Concept.ConceptSchema],
|
18
|
-
|
19
|
-
user: { type: ObjectId, ref: 'User', index: true }, // Bonnie-specific
|
20
|
-
bundle: { type: ObjectId, ref: 'Bundle' }, // Cypress-specific
|
21
|
-
measures: [{ type: ObjectId, ref: 'Measure' }],
|
22
|
-
},
|
23
|
-
// Options
|
24
|
-
{
|
25
|
-
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' },
|
26
|
-
}
|
27
|
-
);
|
28
|
-
|
29
|
-
module.exports.ValueSetSchema = ValueSetSchema;
|
30
|
-
module.exports.ValueSet = mongoose.model('value_set', ValueSetSchema);
|
@@ -1,174 +0,0 @@
|
|
1
|
-
module QDM
|
2
|
-
# Measure contains the information necessary to represent the CQL version of a Clinical Quality Measure,
|
3
|
-
# As needed by the Bonnie & Cypress applications
|
4
|
-
class Measure
|
5
|
-
include Mongoid::Document
|
6
|
-
include Mongoid::Timestamps
|
7
|
-
|
8
|
-
DEFAULT_EFFECTIVE_DATE = Time.gm(2012, 12, 31, 23, 59).to_i
|
9
|
-
MP_START_DATE = Time.gm(2012, 1, 1, 0, 0).to_i
|
10
|
-
TYPES = %w[ep eh].freeze
|
11
|
-
|
12
|
-
IPP = 'IPP'.freeze
|
13
|
-
DENOM = 'DENOM'.freeze
|
14
|
-
NUMER = 'NUMER'.freeze
|
15
|
-
NUMEX = 'NUMEX'.freeze
|
16
|
-
DENEXCEP = 'DENEXCEP'.freeze
|
17
|
-
DENEX = 'DENEX'.freeze
|
18
|
-
MSRPOPL = 'MSRPOPL'.freeze
|
19
|
-
OBSERV = 'OBSERV'.freeze
|
20
|
-
MSRPOPLEX = 'MSRPOPLEX'.freeze
|
21
|
-
|
22
|
-
STRAT = 'STRAT'.freeze
|
23
|
-
|
24
|
-
ALL_POPULATION_CODES = [STRAT, IPP, DENOM, DENEX, NUMER, NUMEX, DENEXCEP, MSRPOPL, OBSERV, MSRPOPLEX].freeze
|
25
|
-
|
26
|
-
CQL_SKIP_STATEMENTS = ['SDE Ethnicity', 'SDE Payer', 'SDE Race', 'SDE Sex'].freeze
|
27
|
-
|
28
|
-
# ID/other measure information
|
29
|
-
field :id, type: String
|
30
|
-
field :measure_id, type: String
|
31
|
-
field :hqmf_id, type: String
|
32
|
-
field :hqmf_set_id, type: String
|
33
|
-
field :hqmf_version_number, type: Integer
|
34
|
-
field :cms_id, type: String
|
35
|
-
field :title, type: String, default: ''
|
36
|
-
field :description, type: String, default: ''
|
37
|
-
field :type, type: String
|
38
|
-
field :category, type: String, default: 'uncategorized'
|
39
|
-
|
40
|
-
# Measure type variables
|
41
|
-
field :episode_of_care, type: Boolean
|
42
|
-
field :continuous_variable, type: Boolean
|
43
|
-
field :episode_ids, type: Array
|
44
|
-
|
45
|
-
# Publishing data (used by Bonnie)
|
46
|
-
field :published, type: Boolean
|
47
|
-
field :publish_date, type: Date
|
48
|
-
field :version, type: Integer
|
49
|
-
|
50
|
-
# ELM/CQL Measure-logic related data
|
51
|
-
field :elm_annotations, type: Hash
|
52
|
-
field :cql, type: Array
|
53
|
-
field :elm, type: Array
|
54
|
-
field :main_cql_library, type: String
|
55
|
-
field :cql_statement_dependencies, type: Hash
|
56
|
-
|
57
|
-
# HQMF/Tacoma-specific Measure-logic related data
|
58
|
-
field :population_criteria, type: Hash
|
59
|
-
field :data_criteria, type: Hash
|
60
|
-
field :source_data_criteria, type: Hash
|
61
|
-
field :measure_period, type: Hash
|
62
|
-
field :measure_attributes, type: Array
|
63
|
-
field :populations, type: Array
|
64
|
-
field :populations_cql_map, type: Hash
|
65
|
-
field :observations, type: Array
|
66
|
-
# TODO: Depending on how we restructure the Measure/Population object, may be deleted in the future
|
67
|
-
field :population_ids, type: Hash
|
68
|
-
|
69
|
-
field :value_set_oids, type: Array, default: []
|
70
|
-
field :value_set_oid_version_objects, type: Array, default: []
|
71
|
-
|
72
|
-
field :complexity, type: Hash
|
73
|
-
|
74
|
-
# Relations to other model classes
|
75
|
-
belongs_to :user
|
76
|
-
belongs_to :bundle, class_name: 'HealthDataStandards::CQM::Bundle'
|
77
|
-
has_and_belongs_to_many :patients, inverse_of: nil
|
78
|
-
has_one :package, class_name: 'CqlMeasurePackage', inverse_of: :measure, dependent: :destroy
|
79
|
-
|
80
|
-
scope :by_measure_id, ->(id) { where('measure_id' => id) }
|
81
|
-
scope :by_type, ->(type) { where('type' => type) }
|
82
|
-
scope :by_user, ->(user) { where user_id: user.id }
|
83
|
-
|
84
|
-
index 'user_id' => 1
|
85
|
-
# Find the measures matching a patient
|
86
|
-
def self.for_patient(record)
|
87
|
-
where user_id: record.user_id, hqmf_set_id: { '$in' => record.measure_ids }
|
88
|
-
end
|
89
|
-
|
90
|
-
def value_sets
|
91
|
-
options = { oid: value_set_oids }
|
92
|
-
options[:user_id] = user.id if user?
|
93
|
-
@value_sets ||= HealthDataStandards::SVS::ValueSet.in(options)
|
94
|
-
@value_sets
|
95
|
-
end
|
96
|
-
|
97
|
-
# Returns the hqmf-parser's ruby implementation of an HQMF document.
|
98
|
-
# Rebuild from population_criteria, data_criteria, and measure_period JSON
|
99
|
-
def as_hqmf_model
|
100
|
-
json = {
|
101
|
-
'id' => measure_id,
|
102
|
-
'title' => title,
|
103
|
-
'description' => description,
|
104
|
-
'population_criteria' => population_criteria,
|
105
|
-
'data_criteria' => data_criteria,
|
106
|
-
'source_data_criteria' => source_data_criteria,
|
107
|
-
'measure_period' => measure_period,
|
108
|
-
'attributes' => measure_attributes,
|
109
|
-
'populations' => populations,
|
110
|
-
'hqmf_id' => hqmf_id,
|
111
|
-
'hqmf_set_id' => hqmf_set_id,
|
112
|
-
'hqmf_version_number' => hqmf_version_number,
|
113
|
-
'cms_id' => cms_id
|
114
|
-
}
|
115
|
-
HQMF::Document.from_json(json)
|
116
|
-
end
|
117
|
-
|
118
|
-
def all_data_criteria
|
119
|
-
as_hqmf_model.all_data_criteria
|
120
|
-
end
|
121
|
-
|
122
|
-
# Note whether or not the measure is a continuous variable measure.
|
123
|
-
before_save :set_continuous_variable
|
124
|
-
def set_continuous_variable
|
125
|
-
# The return value of this function is not related to whether or not this
|
126
|
-
# measure is a CV measure. The true return value ensures false is not
|
127
|
-
# accidentally returned here, which would cause the chain of 'before_*' to
|
128
|
-
# stop executing.
|
129
|
-
self.continuous_variable = populations.map(&:keys).flatten.uniq.include? HQMF::PopulationCriteria::MSRPOPL
|
130
|
-
true
|
131
|
-
end
|
132
|
-
|
133
|
-
# When saving calculate the cyclomatic complexity of the measure
|
134
|
-
# TODO: Do we want to consider a measure other than "cyclomatic complexity" for CQL?
|
135
|
-
# TODO: THIS IS NOT CYCLOMATIC COMPLEXITY, ALL MULTIPLE ELEMENT EXPRESSIONS GET COUNTED AS HIGHER COMPLEXITY, NOT JUST LOGICAL
|
136
|
-
before_save :calculate_complexity
|
137
|
-
def calculate_complexity
|
138
|
-
# We calculate the complexity for each statement, and (at least for now) store the result in the same way
|
139
|
-
# we store the complexity for QDM variables
|
140
|
-
# TODO: consider whether this is too much of a force fit
|
141
|
-
self.complexity = { variables: [] }
|
142
|
-
# Recursively look through an expression to count the logical branches
|
143
|
-
def count_expression_logical_branches(expression)
|
144
|
-
case expression
|
145
|
-
when nil
|
146
|
-
0
|
147
|
-
when Array
|
148
|
-
expression.map { |exp| count_expression_logical_branches(exp) }.sum
|
149
|
-
when Hash
|
150
|
-
case expression['type']
|
151
|
-
when 'And', 'Or', 'Not'
|
152
|
-
count_expression_logical_branches(expression['operand'])
|
153
|
-
when 'Query'
|
154
|
-
# TODO: Do we need to look into the source side of the query? Can there be logical operators there?
|
155
|
-
count_expression_logical_branches(expression['where']) + count_expression_logical_branches(expression['relationship'])
|
156
|
-
else
|
157
|
-
1
|
158
|
-
end
|
159
|
-
else
|
160
|
-
0
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
# Determine the complexity of each statement
|
165
|
-
elm.each do |elm|
|
166
|
-
next unless (statements = elm.try(:[], 'library').try(:[], 'statements').try(:[], 'def'))
|
167
|
-
statements.each do |statement|
|
168
|
-
complexity[:variables] << { name: statement['name'], complexity: count_expression_logical_branches(statement['expression']) }
|
169
|
-
end
|
170
|
-
end
|
171
|
-
complexity
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
module QDM
|
2
|
-
# ValueSet represents a collection of Concepts, used by the Measures to specify a set of codes for a particular topic
|
3
|
-
class ValueSet
|
4
|
-
include Mongoid::Document
|
5
|
-
field :oid, type: String
|
6
|
-
field :display_name, type: String
|
7
|
-
field :version, type: String
|
8
|
-
field :user_id, type: String # Eventually we need to delete this from bundles when exporting
|
9
|
-
field :categories, type: Hash
|
10
|
-
|
11
|
-
index(oid: 1)
|
12
|
-
embeds_many :concepts
|
13
|
-
index 'concepts.code' => 1
|
14
|
-
index 'concepts.code_system' => 1
|
15
|
-
index 'concepts.code_system_name' => 1
|
16
|
-
index 'bundle_id' => 1
|
17
|
-
scope :by_oid, ->(oid) { where(oid: oid) }
|
18
|
-
|
19
|
-
# Provides an Array of Hashes. Each code system gets its own Hash
|
20
|
-
# The hash has a key of "set" for the code system name and "values"
|
21
|
-
# for the actual code list
|
22
|
-
def code_set_map
|
23
|
-
codes = []
|
24
|
-
concept_pairs = concepts.each_with_object({}) do |concept, memo|
|
25
|
-
memo[concept.code_system_name] ||= []
|
26
|
-
memo[concept.code_system_name] << concept.code
|
27
|
-
end
|
28
|
-
concept_pairs.each_pair do |code_set, code_list|
|
29
|
-
codes << { 'set' => code_set, 'values' => code_list }
|
30
|
-
end
|
31
|
-
|
32
|
-
codes
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.load_from_xml(doc)
|
36
|
-
doc.root.add_namespace_definition('vs', 'urn:ihe:iti:svs:2008')
|
37
|
-
vs_element = doc.at_xpath('/vs:RetrieveValueSetResponse/vs:ValueSet|/vs:RetrieveMultipleValueSetsResponse/vs:DescribedValueSet')
|
38
|
-
return unless vs_element
|
39
|
-
vs = ValueSet.new(oid: vs_element['ID'], display_name: vs_element['displayName'], version: vs_element['version'])
|
40
|
-
vs.concepts = extract_concepts(vs_element)
|
41
|
-
vs.categories = extract_categories(vs_element)
|
42
|
-
vs
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.extract_concepts(vs_element)
|
46
|
-
vs_element.xpath('//vs:Concept').collect do |con|
|
47
|
-
code_system_name = HealthDataStandards::Util::CodeSystemHelper::CODE_SYSTEMS[con['codeSystem']] || con['codeSystemName']
|
48
|
-
Concept.new(code: con['code'],
|
49
|
-
code_system_name: code_system_name,
|
50
|
-
code_system_version: con['codeSystemVersion'],
|
51
|
-
display_name: con['displayName'], code_system: con['codeSystem'])
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.extract_categories(vs_element)
|
56
|
-
category_hash = Hash.new { |h, k| h[k] = [] }
|
57
|
-
groups_with_categories = vs_element.xpath("//vs:Group/@ID[../@displayName='CATEGORY']")
|
58
|
-
groups_with_categories.each do |group_number|
|
59
|
-
measure = vs_element.xpath("//vs:Group[@displayName='CMS eMeasure ID' and @ID='#{group_number}']/vs:Keyword").text
|
60
|
-
categories_for_group = vs_element.xpath("//vs:Group[@displayName='CATEGORY' and @ID='#{group_number}']/vs:Keyword")
|
61
|
-
categories_for_group.each do |category|
|
62
|
-
category_hash[measure] << category.text
|
63
|
-
end
|
64
|
-
end
|
65
|
-
!category_hash.empty? ? category_hash : nil
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|