health-data-standards 0.8.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/lib/health-data-standards/export/ccr.rb +1 -1
- data/lib/health-data-standards/export/csv.rb +6 -1
- data/lib/health-data-standards/export/green_c32/entry.rb +1 -1
- data/lib/health-data-standards/export/green_c32/record.rb +15 -0
- data/lib/health-data-standards/export/template_helper.rb +0 -2
- data/lib/health-data-standards/export/view_helper.rb +28 -2
- data/lib/health-data-standards/import/c32/allergy_importer.rb +12 -8
- data/lib/health-data-standards/import/c32/care_goal_importer.rb +39 -0
- data/lib/health-data-standards/import/c32/condition_importer.rb +10 -4
- data/lib/health-data-standards/import/c32/encounter_importer.rb +16 -10
- data/lib/health-data-standards/import/c32/immunization_importer.rb +2 -2
- data/lib/health-data-standards/import/c32/insurance_provider_importer.rb +42 -0
- data/lib/health-data-standards/import/c32/medical_equipment_importer.rb +45 -0
- data/lib/health-data-standards/import/c32/medication_importer.rb +35 -48
- data/lib/health-data-standards/import/c32/organization_importer.rb +1 -1
- data/lib/health-data-standards/import/c32/patient_importer.rb +3 -3
- data/lib/health-data-standards/import/c32/procedure_importer.rb +12 -8
- data/lib/health-data-standards/import/c32/result_importer.rb +11 -14
- data/lib/health-data-standards/import/c32/section_importer.rb +60 -29
- data/lib/health-data-standards/import/ccda/allergy_importer.rb +20 -0
- data/lib/health-data-standards/import/ccda/care_goal_importer.rb +13 -0
- data/lib/health-data-standards/import/ccda/condition_importer.rb +20 -0
- data/lib/health-data-standards/import/ccda/encounter_importer.rb +18 -0
- data/lib/health-data-standards/import/ccda/immunization_importer.rb +16 -0
- data/lib/health-data-standards/import/ccda/insurance_provider_importer.rb +14 -0
- data/lib/health-data-standards/import/ccda/medical_equipment_importer.rb +16 -0
- data/lib/health-data-standards/import/ccda/medication_importer.rb +19 -0
- data/lib/health-data-standards/import/ccda/patient_importer.rb +29 -0
- data/lib/health-data-standards/import/ccda/procedure_importer.rb +17 -0
- data/lib/health-data-standards/import/ccda/result_importer.rb +13 -0
- data/lib/health-data-standards/import/ccda/vital_sign_importer.rb +12 -0
- data/lib/health-data-standards/import/ccr/patient_importer.rb +16 -3
- data/lib/health-data-standards/import/green_c32/advance_directive_importer.rb +14 -0
- data/lib/health-data-standards/import/green_c32/allergy_importer.rb +1 -1
- data/lib/health-data-standards/import/green_c32/care_goal_importer.rb +26 -0
- data/lib/health-data-standards/import/green_c32/condition_importer.rb +0 -6
- data/lib/health-data-standards/import/green_c32/encounter_importer.rb +1 -6
- data/lib/health-data-standards/import/green_c32/immunization_importer.rb +1 -1
- data/lib/health-data-standards/import/green_c32/medical_equipment_importer.rb +24 -0
- data/lib/health-data-standards/import/green_c32/medication_importer.rb +1 -1
- data/lib/health-data-standards/import/green_c32/procedure_importer.rb +2 -10
- data/lib/health-data-standards/import/green_c32/section_importer.rb +36 -5
- data/lib/health-data-standards/import/green_c32/social_history_importer.rb +1 -6
- data/lib/health-data-standards/import/green_c32/support_importer.rb +22 -0
- data/lib/health-data-standards/models/allergy.rb +1 -1
- data/lib/health-data-standards/models/condition.rb +3 -1
- data/lib/health-data-standards/models/encounter.rb +1 -3
- data/lib/health-data-standards/models/entry.rb +23 -21
- data/lib/health-data-standards/models/guarantor.rb +10 -0
- data/lib/health-data-standards/models/insurance_provider.rb +17 -0
- data/lib/health-data-standards/models/medical_equipment.rb +5 -0
- data/lib/health-data-standards/models/medication.rb +0 -2
- data/lib/health-data-standards/models/person.rb +4 -0
- data/lib/health-data-standards/models/personable.rb +13 -0
- data/lib/health-data-standards/models/procedure.rb +0 -2
- data/lib/health-data-standards/models/provider.rb +1 -6
- data/lib/health-data-standards/models/record.rb +11 -5
- data/lib/health-data-standards/models/support.rb +18 -0
- data/lib/health-data-standards.rb +28 -2
- data/templates/_advance_directive.gc32.erb +8 -0
- data/templates/_allergy.gc32.erb +17 -7
- data/templates/_care_goal.gc32.erb +8 -0
- data/templates/_condition.gc32.erb +4 -6
- data/templates/_conditions.c32.erb +3 -0
- data/templates/_encounter.gc32.erb +1 -7
- data/templates/_entry.gc32.erb +14 -0
- data/templates/_immunization.gc32.erb +4 -2
- data/templates/_insurance_provider.gc32.erb +0 -0
- data/templates/_medical_equipment.c32.erb +6 -0
- data/templates/_medical_equipment.gc32.erb +7 -0
- data/templates/_medication.gc32.erb +26 -14
- data/templates/_medications_no_current.c32.erb +26 -6
- data/templates/_name.gc32.erb +11 -0
- data/templates/_narrative_block.c32.erb +1 -1
- data/templates/_procedure.gc32.erb +6 -4
- data/templates/_result.gc32.erb +2 -8
- data/templates/_results.c32.erb +8 -2
- data/templates/_social_history.gc32.erb +3 -1
- data/templates/_support.gc32.erb +14 -0
- data/templates/_vital_sign.gc32.erb +2 -7
- data/templates/_vital_signs.c32.erb +8 -2
- data/templates/record.gc32.erb +81 -0
- data/templates/show.c32.erb +1 -1
- metadata +48 -16
- data/lib/health-data-standards/models/comment.rb +0 -2
- data/lib/health-data-standards/models/social_history.rb +0 -3
@@ -15,10 +15,11 @@ module HealthDataStandards
|
|
15
15
|
# @param [String] status_xpath XPath expression to find the status element as a child of the desired CDA
|
16
16
|
# entry. Defaults to nil. If not provided, a status will not be checked for since it is not applicable
|
17
17
|
# to all enrty types
|
18
|
-
def initialize(entry_xpath, code_xpath="./cda:code", status_xpath=nil, description_xpath="./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] ")
|
18
|
+
def initialize(entry_xpath, code_xpath="./cda:code", status_xpath=nil,priority_xpath=nil, description_xpath="./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] ")
|
19
19
|
@entry_xpath = entry_xpath
|
20
20
|
@code_xpath = code_xpath
|
21
21
|
@status_xpath = status_xpath
|
22
|
+
@priority_xpath = priority_xpath
|
22
23
|
@description_xpath = description_xpath
|
23
24
|
@check_for_usable = true # Pilot tools will set this to false
|
24
25
|
end
|
@@ -48,16 +49,7 @@ module HealthDataStandards
|
|
48
49
|
entry_list = []
|
49
50
|
entry_elements = doc.xpath(@entry_xpath)
|
50
51
|
entry_elements.each do |entry_element|
|
51
|
-
entry =
|
52
|
-
extract_codes(entry_element, entry)
|
53
|
-
extract_dates(entry_element, entry)
|
54
|
-
extract_value(entry_element, entry)
|
55
|
-
if @status_xpath
|
56
|
-
extract_status(entry_element, entry)
|
57
|
-
end
|
58
|
-
if @description_xpath
|
59
|
-
extract_description(entry_element, entry, id_map)
|
60
|
-
end
|
52
|
+
entry = create_entry(entry_element, id_map)
|
61
53
|
if @check_for_usable
|
62
54
|
entry_list << entry if entry.usable?
|
63
55
|
else
|
@@ -66,6 +58,23 @@ module HealthDataStandards
|
|
66
58
|
end
|
67
59
|
entry_list
|
68
60
|
end
|
61
|
+
|
62
|
+
def create_entry(entry_element, id_map={})
|
63
|
+
entry = Entry.new
|
64
|
+
extract_codes(entry_element, entry)
|
65
|
+
extract_dates(entry_element, entry)
|
66
|
+
extract_value(entry_element, entry)
|
67
|
+
if @status_xpath
|
68
|
+
extract_status(entry_element, entry)
|
69
|
+
end
|
70
|
+
if @priority_xpath
|
71
|
+
extract_priority(entry_element, entry)
|
72
|
+
end
|
73
|
+
if @description_xpath
|
74
|
+
extract_description(entry_element, entry, id_map)
|
75
|
+
end
|
76
|
+
entry
|
77
|
+
end
|
69
78
|
|
70
79
|
private
|
71
80
|
|
@@ -83,6 +92,17 @@ module HealthDataStandards
|
|
83
92
|
end
|
84
93
|
end
|
85
94
|
|
95
|
+
def extract_priority(parent_element, entry)
|
96
|
+
priority_element = parent_element.at_xpath(@priority_xpath)
|
97
|
+
if priority_element
|
98
|
+
case priority_element['code']
|
99
|
+
when '8319008'
|
100
|
+
entry.ordinality = :principal
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
86
106
|
def extract_description(parent_element, entry, id_map)
|
87
107
|
code_elements = parent_element.xpath(@description_xpath)
|
88
108
|
code_elements.each do |code_element|
|
@@ -108,18 +128,18 @@ module HealthDataStandards
|
|
108
128
|
end
|
109
129
|
end
|
110
130
|
|
111
|
-
def extract_dates(parent_element, entry)
|
112
|
-
if parent_element.at_xpath(
|
113
|
-
entry.time = HL7Helper.timestamp_to_integer(parent_element.at_xpath(
|
131
|
+
def extract_dates(parent_element, entry, element_name="effectiveTime")
|
132
|
+
if parent_element.at_xpath("cda:#{element_name}")
|
133
|
+
entry.time = HL7Helper.timestamp_to_integer(parent_element.at_xpath("cda:#{element_name}")['value'])
|
114
134
|
end
|
115
|
-
if parent_element.at_xpath(
|
116
|
-
entry.start_time = HL7Helper.timestamp_to_integer(parent_element.at_xpath(
|
135
|
+
if parent_element.at_xpath("cda:#{element_name}/cda:low")
|
136
|
+
entry.start_time = HL7Helper.timestamp_to_integer(parent_element.at_xpath("cda:#{element_name}/cda:low")['value'])
|
117
137
|
end
|
118
|
-
if parent_element.at_xpath(
|
119
|
-
entry.end_time = HL7Helper.timestamp_to_integer(parent_element.at_xpath(
|
138
|
+
if parent_element.at_xpath("cda:#{element_name}/cda:high")
|
139
|
+
entry.end_time = HL7Helper.timestamp_to_integer(parent_element.at_xpath("cda:#{element_name}/cda:high")['value'])
|
120
140
|
end
|
121
|
-
if parent_element.at_xpath(
|
122
|
-
entry.time = HL7Helper.timestamp_to_integer(parent_element.at_xpath(
|
141
|
+
if parent_element.at_xpath("cda:#{element_name}/cda:center")
|
142
|
+
entry.time = HL7Helper.timestamp_to_integer(parent_element.at_xpath("cda:#{element_name}/cda:center")['value'])
|
123
143
|
end
|
124
144
|
end
|
125
145
|
|
@@ -128,24 +148,35 @@ module HealthDataStandards
|
|
128
148
|
if value_element
|
129
149
|
value = value_element['value']
|
130
150
|
unit = value_element['unit']
|
151
|
+
value ||= value_element.text
|
131
152
|
if value
|
132
|
-
entry.set_value(value, unit)
|
153
|
+
entry.set_value(value.strip, unit)
|
133
154
|
end
|
155
|
+
|
134
156
|
end
|
135
157
|
end
|
136
158
|
|
137
159
|
def import_actor(actor_element)
|
138
160
|
return ProviderImporter.instance.extract_provider(actor_element)
|
139
161
|
end
|
162
|
+
|
163
|
+
def import_organization(organization_element)
|
164
|
+
return OrganizationImporter.instance.extract_organization(organization_element)
|
165
|
+
end
|
140
166
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
167
|
+
def import_person(person_element)
|
168
|
+
return unless person_element
|
169
|
+
person = Person.new
|
170
|
+
name_element = person_element.at_xpath("./cda:name")
|
171
|
+
if name_element
|
172
|
+
person.title = name_element.at_xpath("./cda:title").try(:text)
|
173
|
+
person.given_name = name_element.at_xpath("./cda:given").try(:text)
|
174
|
+
person.family_name = name_element.at_xpath("./cda:family").try(:text)
|
175
|
+
end
|
176
|
+
person.addresses = person_element.xpath("./cda:addr").map { |addr| import_address(addr) }
|
177
|
+
person.telecoms = person_element.xpath("./cda:telecom").map { |tele| import_telecom(tele) }
|
178
|
+
return person
|
179
|
+
end
|
149
180
|
|
150
181
|
def import_address(address_element)
|
151
182
|
address = Address.new
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module CCDA
|
4
|
+
class AllergyImporter < C32::AllergyImporter
|
5
|
+
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@entry_xpath = "//cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.7']"
|
9
|
+
@code_xpath = "./cda:participant/cda:participantRole/cda:playingEntity/cda:code"
|
10
|
+
@description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value]"
|
11
|
+
@type_xpath = "./cda:code"
|
12
|
+
@reaction_xpath = "./cda:entryRelationship[@typeCode='MFST']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.9']/cda:value"
|
13
|
+
@severity_xpath = "./cda:entryRelationship[@typeCode='SUBJ']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.8']/cda:value"
|
14
|
+
@status_xpath = "./cda:entryRelationship[@typeCode='SUBJ']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.28']/cda:value"
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module CCDA
|
4
|
+
class CareGoalImporter < C32::CareGoalImporter
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.2.10']/cda:entry/cda:*"
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module CCDA
|
4
|
+
class ConditionImporter < C32::ConditionImporter
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.2.5' or cda:templateId/@root='2.16.840.1.113883.10.20.22.2.5.1']/cda:entry/cda:act/cda:entryRelationship/cda:observation"
|
8
|
+
@status_xpath = "./cda:entryRelationship/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.6']/cda:value"
|
9
|
+
@description_xpath = "./cda:text/cda:reference[@value]"
|
10
|
+
@code_xpath = "./cda:value"
|
11
|
+
|
12
|
+
#optional
|
13
|
+
#health status
|
14
|
+
#age at onset
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module CCDA
|
4
|
+
# TODO Extract Discharge Disposition
|
5
|
+
class EncounterImporter < C32::EncounterImporter
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.2.22' or cda:templateId/@root='2.16.840.1.113883.10.20.22.2.22.1']/cda:entry/cda:encounter"
|
9
|
+
@code_xpath = "./cda:code"
|
10
|
+
@status_xpath = "./cda:statusCode"
|
11
|
+
@description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] "
|
12
|
+
@reason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation"
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module CCDA
|
4
|
+
class ImmunizationImporter < C32::ImmunizationImporter
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.2.2' or cda:templateId/@root='2.16.840.1.113883.10.20.22.2.2.1']/cda:entry/cda:substanceAdministration"
|
8
|
+
@code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
|
9
|
+
@description_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code/cda:originalText/cda:reference[@value]"
|
10
|
+
@refusal_reason_xpath = "./cda:entryRelationship[@typeCode='MFST']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.9']/cda:value"
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module CCDA
|
4
|
+
class InsuranceProviderImporter < C32::InsuranceProviderImporter
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@entry_xpath = "//cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.61']"
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module CCDA
|
4
|
+
class MedicalEquipmentImporter < C32::MedicalEquipmentImporter
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.50']/cda:entry/cda:supply"
|
8
|
+
@code_xpath = "./cda:participant/cda:participantRole/cda:playingDevice/cda:code"
|
9
|
+
@description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value]"
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module CCDA
|
4
|
+
|
5
|
+
class MedicationImporter < C32::MedicationImporter
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.2.1' or cda:templateId/@root='2.16.840.1.113883.10.20.22.2.1.1']/cda:entry/cda:substanceAdministration"
|
9
|
+
@code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
|
10
|
+
@description_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code/cda:originalText/cda:reference[@value]"
|
11
|
+
@indication_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.19']/cda:code"
|
12
|
+
@vehicle_xpath = "./cda:participant/cda:participantRole[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.24']/cda:playingEntity/cda:code"
|
13
|
+
@fill_number_xpath = './cda:repeatNumber'
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module CCDA
|
4
|
+
class PatientImporter < C32::PatientImporter
|
5
|
+
|
6
|
+
def initialize(check_usable = true)
|
7
|
+
@section_importers = {}
|
8
|
+
@section_importers[:encounters] = EncounterImporter.new
|
9
|
+
@section_importers[:procedures] = ProcedureImporter.new
|
10
|
+
@section_importers[:results] = ResultImporter.new
|
11
|
+
@section_importers[:vital_signs] = VitalSignImporter.new
|
12
|
+
@section_importers[:medications] = MedicationImporter.new
|
13
|
+
@section_importers[:conditions] = ConditionImporter.new
|
14
|
+
@section_importers[:social_history] = C32::SectionImporter.new("//cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.38' or cda:templateId/@root='2.16.840.1.113883.10.20.15.3.8']")
|
15
|
+
@section_importers[:care_goals] = CareGoalImporter.new
|
16
|
+
@section_importers[:medical_equipment] = MedicalEquipmentImporter.new
|
17
|
+
@section_importers[:allergies] = AllergyImporter.new
|
18
|
+
@section_importers[:immunizations] = ImmunizationImporter.new
|
19
|
+
@section_importers[:insurance_providers] = InsuranceProviderImporter.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_ccda(doc)
|
23
|
+
parse_c32(doc)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module CCDA
|
4
|
+
class ProcedureImporter < C32::ProcedureImporter
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.10.20.22.2.7' or cda:templateId/@root='2.16.840.1.113883.10.20.22.2.7.1']/cda:entry/cda:*"
|
8
|
+
@code_xpath = "./cda:code"
|
9
|
+
@status_xpath = "./cda:statusCode"
|
10
|
+
@description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] "
|
11
|
+
@check_for_usable = true # Pilot tools will set this to false
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module CCDA
|
4
|
+
class ResultImporter < C32::ResultImporter
|
5
|
+
def initialize
|
6
|
+
@entry_xpath = "//cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.2']"
|
7
|
+
@code_xpath = "./cda:code"
|
8
|
+
@description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] "
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module CCDA
|
4
|
+
class VitalSignImporter < C32::VitalSignImporter
|
5
|
+
def initialize
|
6
|
+
super
|
7
|
+
@entry_xpath = "//cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.27']"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -188,9 +188,22 @@ module HealthDataStandards
|
|
188
188
|
patientActor = doc.at_xpath("//ccr:ContinuityOfCareRecord/ccr:Actors/ccr:Actor[ccr:ActorObjectID = \"#{patientActorID}\"]")
|
189
189
|
patientID = patientActor.at_xpath(patient_id_xpath).try(:content)
|
190
190
|
patientID ||= patientActorID
|
191
|
-
|
192
|
-
|
193
|
-
|
191
|
+
|
192
|
+
name_element = patientActor.at_xpath('./ccr:Person/ccr:Name')
|
193
|
+
|
194
|
+
if name_element
|
195
|
+
if name_element.at_xpath("./ccr:CurrentName")
|
196
|
+
patient['first'] = name_element.at_xpath('./ccr:CurrentName/ccr:Given').try(:content)
|
197
|
+
patient['last'] = name_element.at_xpath('./ccr:CurrentName/ccr:Family').try(:content)
|
198
|
+
elsif name_element.at_xpath("./ccr:DisplayName")
|
199
|
+
# this will not work in all cases, but we're using it as a last resort if no CurrentName is found
|
200
|
+
first, last = name_element.at_xpath("./ccr:DisplayName").content.split(" ")
|
201
|
+
patient['first'] = first.strip
|
202
|
+
patient['last'] = last.strip
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
|
194
207
|
birthdate = patientActor.at_xpath('./ccr:Person//ccr:DateOfBirth/ccr:ExactDateTime | ./ccr:Person//ccr:DateOfBirth/ccr:ApproximateDateTime')
|
195
208
|
patient['birthdate'] = Time.parse(birthdate.content).to_i if birthdate
|
196
209
|
|
@@ -9,7 +9,7 @@ module HealthDataStandards
|
|
9
9
|
allergy_element = allergy_xml.xpath("./gc32:allergy")
|
10
10
|
allergy = Allergy.new
|
11
11
|
extract_entry(allergy_element, allergy)
|
12
|
-
allergy
|
12
|
+
extract_code(allergy_element, allergy, "./gc32:type", :type)
|
13
13
|
extract_code(allergy_element, allergy, "./gc32:reaction", :reaction)
|
14
14
|
extract_code(allergy_element, allergy, "./gc32:severity", :severity)
|
15
15
|
allergy
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module GreenC32
|
4
|
+
class CareGoalImporter
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
end
|
9
|
+
|
10
|
+
def import(care_goal_xml)
|
11
|
+
importer = case care_goal_xml.at_xpath("/*").try(:name)
|
12
|
+
when "medication" then MedicationImporter.instance
|
13
|
+
when "immunization" then ImmunizationImporter.instance
|
14
|
+
when "procedure" then ProcedureImporter.instance
|
15
|
+
when "encounter" then EncounterImporter.instance
|
16
|
+
when "medicalEquipment" then MedicalEquipmentImporter.instance
|
17
|
+
else SectionImporter.new
|
18
|
+
end
|
19
|
+
|
20
|
+
return importer.import(care_goal_xml)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -15,7 +15,6 @@ module HealthDataStandards
|
|
15
15
|
condition = Condition.new
|
16
16
|
|
17
17
|
extract_entry(condition_element, condition)
|
18
|
-
extract_name(condition_element, condition)
|
19
18
|
extract_cause_of_death(condition_element, condition)
|
20
19
|
extract_type(condition_element, condition)
|
21
20
|
|
@@ -29,11 +28,6 @@ module HealthDataStandards
|
|
29
28
|
condition.type = extract_node_text(type)
|
30
29
|
end
|
31
30
|
|
32
|
-
def extract_name(condition_xml, condition)
|
33
|
-
name = condition_xml.xpath("./gc32:name").first
|
34
|
-
condition.name = extract_node_text(name)
|
35
|
-
end
|
36
|
-
|
37
31
|
def extract_cause_of_death(condition_xml, condition)
|
38
32
|
condition.cause_of_death = extract_node_attribute(condition_xml, "causeOfDeath")
|
39
33
|
end
|
@@ -18,12 +18,7 @@ module HealthDataStandards
|
|
18
18
|
extract_code(encounter_element, encounter, "./gc32:reasonForVisit", :reason)
|
19
19
|
extract_code(encounter_element, encounter)
|
20
20
|
extract_facility(encounter_element, encounter)
|
21
|
-
|
22
|
-
free_text = encounter_element.xpath("./gc32:freeText").first
|
23
|
-
|
24
|
-
if free_text
|
25
|
-
encounter.free_text = free_text.content
|
26
|
-
end
|
21
|
+
extract_free_text(encounter_element, encounter)
|
27
22
|
|
28
23
|
encounter
|
29
24
|
end
|
@@ -9,7 +9,7 @@ module HealthDataStandards
|
|
9
9
|
immunization_element = immunization_xml.at_xpath("./gc32:immunization")
|
10
10
|
immunization = Immunization.new
|
11
11
|
extract_entry(immunization_element, immunization)
|
12
|
-
extract_time(immunization_element, immunization, "./gc32:
|
12
|
+
extract_time(immunization_element, immunization, "./gc32:effectiveTime")
|
13
13
|
extract_code(immunization_element, immunization, "./gc32:refusalReason")
|
14
14
|
series_number = extract_node_text(immunization_element.at_xpath("./gc32:seriesNumber"))
|
15
15
|
immunization.series_number = series_number.to_i if series_number
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module HealthDataStandards
|
2
|
+
module Import
|
3
|
+
module GreenC32
|
4
|
+
class MedicalEquipmentImporter < SectionImporter
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
super
|
9
|
+
@value = "./gc32:quantity"
|
10
|
+
end
|
11
|
+
|
12
|
+
def import(me_xml)
|
13
|
+
me_xml.root.add_namespace_definition('gc32', "urn:hl7-org:greencda:c32")
|
14
|
+
me_element = me_xml.at_xpath("./gc32:medicalEquipment")
|
15
|
+
me = MedicalEquipment.new
|
16
|
+
extract_entry(me_element, me)
|
17
|
+
me.manufacturer = extract_node_text(me_element.at_xpath("./gc32:manufacturer")).try(:strip)
|
18
|
+
me
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -22,7 +22,7 @@ module HealthDataStandards
|
|
22
22
|
extract_med_code_attribute(med_element, medication, :vehicle)
|
23
23
|
extract_med_code_attribute(med_element, medication, :reaction)
|
24
24
|
extract_med_code_attribute(med_element, medication, :deliveryMethod)
|
25
|
-
medication
|
25
|
+
extract_free_text(med_element, medication, "freeTextSig")
|
26
26
|
medication.fulfillment_instructions = extract_node_text(med_element.at_xpath("./gc32:patientInstructions"))
|
27
27
|
medication.dose_indicator = extract_node_text(med_element.at_xpath("./gc32:doseIndicator"))
|
28
28
|
medication.fulfillment_history = extract_fulfillment_history(med_element)
|
@@ -17,18 +17,10 @@ module HealthDataStandards
|
|
17
17
|
procedure = Procedure.new
|
18
18
|
|
19
19
|
extract_entry(procedure_element, procedure)
|
20
|
-
|
21
|
-
|
20
|
+
extract_code(procedure_element, procedure, xpath="./gc32:site", attribute=:site)
|
22
21
|
procedure
|
23
22
|
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def extract_type(procedure_xml, procedure)
|
28
|
-
type = procedure_xml.xpath("./gc32:type").first
|
29
|
-
procedure.type = extract_node_text(type)
|
30
|
-
end
|
31
|
-
|
23
|
+
|
32
24
|
end
|
33
25
|
end
|
34
26
|
end
|
@@ -11,9 +11,22 @@ module HealthDataStandards
|
|
11
11
|
@value = "./gc32:value"
|
12
12
|
end
|
13
13
|
|
14
|
+
|
15
|
+
def import(entry_xml)
|
16
|
+
generic_import(entry_xml)
|
17
|
+
end
|
18
|
+
|
19
|
+
def generic_import(element_xml, element_name="entry")
|
20
|
+
entry = Entry.new
|
21
|
+
element_xml.root.add_namespace_definition('gc32', "urn:hl7-org:greencda:c32")
|
22
|
+
element = element_xml.at_xpath("./gc32:#{element_name}")
|
23
|
+
extract_entry(element, entry)
|
24
|
+
entry
|
25
|
+
end
|
26
|
+
|
14
27
|
def extract_code(element, entry, xpath="./gc32:code", attribute=:codes)
|
15
28
|
|
16
|
-
code_element = element.
|
29
|
+
code_element = element.at_xpath(xpath)
|
17
30
|
|
18
31
|
return unless code_element
|
19
32
|
|
@@ -27,12 +40,12 @@ module HealthDataStandards
|
|
27
40
|
end
|
28
41
|
|
29
42
|
def extract_description(element, entry)
|
30
|
-
description = element.
|
43
|
+
description = element.at_xpath(@description)
|
31
44
|
entry.description = extract_node_text(description)
|
32
45
|
end
|
33
46
|
|
34
47
|
def extract_status(element, entry)
|
35
|
-
status = extract_node_text(element.
|
48
|
+
status = extract_node_text(element.at_xpath(@status))
|
36
49
|
return unless status
|
37
50
|
entry.status = status
|
38
51
|
end
|
@@ -45,10 +58,20 @@ module HealthDataStandards
|
|
45
58
|
end
|
46
59
|
end
|
47
60
|
|
61
|
+
def extract_name(element, entry, name_element="name")
|
62
|
+
name_element = element.at_xpath("./gc32:#{name_element}")
|
63
|
+
return unless name_element
|
64
|
+
entry.title = name_element.at_xpath("./gc32:title").try(:content)
|
65
|
+
entry.given_name = name_element.at_xpath("./gc32:givenName").try(:content)
|
66
|
+
entry.family_name = name_element.at_xpath("./gc32:familyName").try(:content)
|
67
|
+
end
|
68
|
+
|
48
69
|
def extract_time(element, entry, xpath = "./gc32:effectiveTime", attribute = "time")
|
49
70
|
datetime = element.at_xpath(xpath)
|
50
|
-
|
51
|
-
|
71
|
+
|
72
|
+
return unless datetime && datetime['value']
|
73
|
+
|
74
|
+
entry.send("#{attribute}=", Time.parse(datetime['value']).to_i)
|
52
75
|
end
|
53
76
|
|
54
77
|
def extract_interval(element, entry, element_name="effectiveTime")
|
@@ -79,6 +102,8 @@ module HealthDataStandards
|
|
79
102
|
extract_status(element, entry)
|
80
103
|
extract_value(element, entry)
|
81
104
|
extract_effective_time(element, entry)
|
105
|
+
entry.free_text = element.at_xpath("./gc32:freeText").try(:inner_text)
|
106
|
+
entry
|
82
107
|
end
|
83
108
|
|
84
109
|
def extract_organization(organization_element)
|
@@ -96,6 +121,7 @@ module HealthDataStandards
|
|
96
121
|
end
|
97
122
|
|
98
123
|
def extract_address(address_element)
|
124
|
+
return unless address_element
|
99
125
|
address = Address.new
|
100
126
|
address.street = address_element.xpath("./gc32:street").map { |st| extract_node_text(st) }
|
101
127
|
address.city = extract_node_text(address_element.xpath("./gc32:city"))
|
@@ -105,6 +131,7 @@ module HealthDataStandards
|
|
105
131
|
end
|
106
132
|
|
107
133
|
def extract_telecom(telecom_element)
|
134
|
+
return unless telecom_element
|
108
135
|
telecom = Telecom.new
|
109
136
|
telecom.use = extract_node_attribute(telecom_element, :type)
|
110
137
|
telecom.value = extract_node_attribute(telecom_element, :value)
|
@@ -112,6 +139,10 @@ module HealthDataStandards
|
|
112
139
|
telecom
|
113
140
|
end
|
114
141
|
|
142
|
+
def extract_free_text(element, entry, free_text_element="freeText")
|
143
|
+
entry.free_text = extract_node_text(element.at_xpath("./gc32:#{free_text_element}"))
|
144
|
+
end
|
145
|
+
|
115
146
|
|
116
147
|
private
|
117
148
|
|