cqm-models 1.0.3 → 1.1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|