health-data-standards 0.3.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/Gemfile +5 -2
  2. data/Rakefile +6 -1
  3. data/VERSION +1 -1
  4. data/lib/health-data-standards.rb +27 -2
  5. data/lib/health-data-standards/export/view_helper.rb +15 -16
  6. data/lib/health-data-standards/ext/string.rb +5 -0
  7. data/lib/health-data-standards/ext/symbol.rb +8 -0
  8. data/lib/health-data-standards/import/c32/allergy_importer.rb +42 -0
  9. data/lib/health-data-standards/import/c32/encounter_importer.rb +80 -0
  10. data/lib/health-data-standards/import/c32/immunization_importer.rb +61 -0
  11. data/lib/health-data-standards/import/c32/medication_importer.rb +138 -0
  12. data/lib/health-data-standards/import/c32/patient_importer.rb +139 -0
  13. data/lib/health-data-standards/import/c32/procedure_importer.rb +55 -0
  14. data/lib/health-data-standards/import/c32/result_importer.rb +58 -0
  15. data/lib/health-data-standards/import/c32/section_importer.rb +214 -0
  16. data/lib/health-data-standards/import/c32/vital_sign_importer.rb +12 -0
  17. data/lib/health-data-standards/models/allergy.rb +4 -0
  18. data/lib/health-data-standards/models/encounter.rb +7 -0
  19. data/lib/health-data-standards/models/entry.rb +131 -3
  20. data/lib/health-data-standards/models/fulfillment_history.rb +11 -0
  21. data/lib/health-data-standards/models/immunization.rb +5 -0
  22. data/lib/health-data-standards/models/lab_result.rb +4 -0
  23. data/lib/health-data-standards/models/medication.rb +25 -0
  24. data/lib/health-data-standards/models/order_information.rb +9 -0
  25. data/lib/health-data-standards/models/procedure.rb +4 -0
  26. data/lib/health-data-standards/models/record.rb +1 -0
  27. data/lib/health-data-standards/util/code_system_helper.rb +41 -0
  28. data/lib/health-data-standards/util/hl7_helper.rb +25 -0
  29. data/templates/_allergies.c32.erb +3 -1
  30. data/templates/_care_goals.c32.erb +1 -1
  31. data/templates/_code_with_reference.c32.erb +10 -5
  32. data/templates/_conditions.c32.erb +2 -2
  33. data/templates/_encounters.c32.erb +2 -1
  34. data/templates/_immunizations.c32.erb +2 -1
  35. data/templates/_medical_equipment.c32.erb +1 -1
  36. data/templates/_medications.c32.erb +2 -1
  37. data/templates/_narrative_block.c32.erb +14 -0
  38. data/templates/_procedures.c32.erb +2 -1
  39. data/templates/_results.c32.erb +2 -2
  40. data/templates/_social_history.c32.erb +1 -1
  41. data/templates/_vital_signs.c32.erb +2 -2
  42. metadata +37 -16
data/Gemfile CHANGED
@@ -2,5 +2,8 @@ source "http://rubygems.org"
2
2
 
3
3
  gemspec :development_group => :test
4
4
 
5
- gem 'rake'
6
- gem 'pry'
5
+ group :development do
6
+ gem 'rake'
7
+ gem 'pry'
8
+ gem 'cover_me'
9
+ end
data/Rakefile CHANGED
@@ -1,7 +1,12 @@
1
1
  require 'rake/testtask'
2
2
 
3
- Rake::TestTask.new do |t|
3
+ Rake::TestTask.new(:test_unit) do |t|
4
4
  t.libs << "test"
5
5
  t.test_files = FileList['test/**/*_test.rb']
6
6
  t.verbose = true
7
+ end
8
+
9
+ task :test => [:test_unit] do
10
+ require 'cover_me'
11
+ CoverMe.complete!
7
12
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.5.0
@@ -2,9 +2,16 @@ require 'erubis'
2
2
  require 'active_support'
3
3
  require 'mongoid'
4
4
  require 'uuid'
5
- require 'quality-measure-engine'
6
5
  require 'builder'
7
6
  require 'csv'
7
+ require 'nokogiri'
8
+
9
+ # Freedom patches
10
+ require_relative 'health-data-standards/ext/symbol'
11
+ require_relative 'health-data-standards/ext/string'
12
+
13
+ require_relative 'health-data-standards/util/hl7_helper'
14
+ require_relative 'health-data-standards/util/code_system_helper'
8
15
 
9
16
  require_relative 'health-data-standards/export/template_helper'
10
17
  require_relative 'health-data-standards/export/view_helper'
@@ -14,4 +21,22 @@ require_relative 'health-data-standards/export/ccr'
14
21
  require_relative 'health-data-standards/export/csv'
15
22
 
16
23
  require_relative 'health-data-standards/models/entry'
17
- require_relative 'health-data-standards/models/record'
24
+ require_relative 'health-data-standards/models/allergy'
25
+ require_relative 'health-data-standards/models/encounter'
26
+ require_relative 'health-data-standards/models/immunization'
27
+ require_relative 'health-data-standards/models/fulfillment_history'
28
+ require_relative 'health-data-standards/models/order_information'
29
+ require_relative 'health-data-standards/models/medication'
30
+ require_relative 'health-data-standards/models/procedure'
31
+ require_relative 'health-data-standards/models/lab_result'
32
+ require_relative 'health-data-standards/models/record'
33
+
34
+ require_relative 'health-data-standards/import/c32/section_importer'
35
+ require_relative 'health-data-standards/import/c32/allergy_importer'
36
+ require_relative 'health-data-standards/import/c32/encounter_importer'
37
+ require_relative 'health-data-standards/import/c32/immunization_importer'
38
+ require_relative 'health-data-standards/import/c32/medication_importer'
39
+ require_relative 'health-data-standards/import/c32/procedure_importer'
40
+ require_relative 'health-data-standards/import/c32/result_importer'
41
+ require_relative 'health-data-standards/import/c32/vital_sign_importer'
42
+ require_relative 'health-data-standards/import/c32/patient_importer'
@@ -1,23 +1,22 @@
1
1
  module HealthDataStandards
2
2
  module Export
3
3
  module ViewHelper
4
- def code_display(entry, tag_name='code', extra_content=nil)
5
- if entry.single_code_value?
6
- code = entry.codes.first[1].first
7
- code_system_oid = QME::Importer::CodeSystemHelper.oid_for_code_system(entry.codes.first[0])
8
- "<#{tag_name} code=\"#{code}\" codeSystem=\"#{code_system_oid}\" #{extra_content}><originalText>#{ERB::Util.html_escape entry.description}</originalText></#{tag_name}>"
4
+ def code_display(entry, options={})
5
+ options['tag_name'] ||= 'code'
6
+ code_string = nil
7
+ preferred_code = entry.preferred_code(options['preferred_code_sets'])
8
+ if preferred_code
9
+ code_system_oid = HealthDataStandards::Util::CodeSystemHelper.oid_for_code_system(preferred_code['code_set'])
10
+ code_string = "<#{options['tag_name']} code=\"#{preferred_code['code']}\" codeSystem=\"#{code_system_oid}\" #{options['extra_content']}>"
9
11
  else
10
- all_codes = []
11
- entry.codes.each_pair {|key, values| values.each {|v| all_codes << {:set => key, :value => v}}}
12
- first_code = all_codes.first
13
- code_string = "<#{tag_name} code=\"#{first_code[:value]}\" codeSystem=\"#{QME::Importer::CodeSystemHelper.oid_for_code_system(first_code[:set])}\">\n"
14
- code_string += "<originalText>#{ERB::Util.html_escape entry.description}</originalText>\n"
15
- all_codes[1..-1].each do |cv|
16
- code_string += "<translation code=\"#{cv[:value]}\" codeSystem=\"#{QME::Importer::CodeSystemHelper.oid_for_code_system(cv[:set])}\"/>\n"
17
- end
18
- code_string += "</#{tag_name}>"
19
- code_string
12
+ code_string = "<#{options['tag_name']} nullFlavor=\"UNK\" #{options['extra_content']}>"
20
13
  end
14
+ code_string += "<originalText>#{ERB::Util.html_escape entry.description}</originalText>"
15
+ entry.translation_codes(options['preferred_code_sets']).each do |translation|
16
+ code_string += "<translation code=\"#{translation['code']}\" codeSystem=\"#{HealthDataStandards::Util::CodeSystemHelper.oid_for_code_system(translation['code_set'])}\"/>\n"
17
+ end
18
+ code_string += "</#{options['tag_name']}>"
19
+ code_string
21
20
  end
22
21
 
23
22
  def status_code_for(entry)
@@ -29,7 +28,7 @@ module HealthDataStandards
29
28
  when 'resolved'
30
29
  '413322009'
31
30
  end
32
- end
31
+ end
33
32
  end
34
33
  end
35
34
  end
@@ -0,0 +1,5 @@
1
+ class String
2
+ def to_boolean
3
+ ['1', 'true', 't'].include?(self.downcase)
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ class Symbol
2
+ # Will take the current symbol and append an "=" to the end of it.
3
+ # So :bacon will become :bacon=. It is assumed that this would be
4
+ # passed to Object#send to set the value of something
5
+ def to_setter
6
+ (self.to_s + '=').to_sym
7
+ end
8
+ end
@@ -0,0 +1,42 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module C32
4
+ class AllergyImporter < SectionImporter
5
+
6
+ def initialize
7
+ @entry_xpath = "//cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.18']"
8
+ @code_xpath = "./cda:participant/cda:participantRole/cda:playingEntity/cda:code"
9
+ @description_xpath = "./cda:code/cda:originalText/cda:reference[@value] | ./cda:text/cda:reference[@value] "
10
+ @id_map = {}
11
+ end
12
+
13
+ # Traverses that HITSP C32 document passed in using XPath and creates an Array of Entry
14
+ # objects based on what it finds
15
+ # @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
16
+ # will have the "cda" namespace registered to "urn:hl7-org:v3"
17
+ # measure definition
18
+ # @return [Array] will be a list of Entry objects
19
+ def create_entries(doc,id_map = {})
20
+ @id_map = id_map
21
+ allergy_list = []
22
+ entry_elements = doc.xpath(@entry_xpath)
23
+ entry_elements.each do |entry_element|
24
+ allergy = Allergy.new
25
+ extract_codes(entry_element, allergy)
26
+ extract_dates(entry_element, allergy)
27
+ extract_description(entry_element, allergy, id_map)
28
+
29
+ allergy.reaction = extract_code(entry_element,
30
+ "./cda:entryRelationship[@typeCode='MFST']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.54']/cda:value")
31
+
32
+ allergy.severity = extract_code(entry_element,
33
+ "./cda:entryRelationship[@typeCode='MFST']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.54']/cda:entryRelationship[@typeCode='SUBJ']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.55']/cda:value")
34
+
35
+ allergy_list << allergy
36
+ end
37
+ allergy_list
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,80 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module C32
4
+ # TODO Extract Discharge Disposition
5
+ class EncounterImporter < SectionImporter
6
+
7
+ def initialize
8
+ @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.127']/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
+ @check_for_usable = true # Pilot tools will set this to false
13
+ @id_map = {}
14
+ end
15
+
16
+ # Traverses that HITSP C32 document passed in using XPath and creates an Array of Entry
17
+ # objects based on what it finds
18
+ # @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
19
+ # will have the "cda" namespace registered to "urn:hl7-org:v3"
20
+ # measure definition
21
+ # @return [Array] will be a list of Entry objects
22
+ def create_entries(doc,id_map = {})
23
+ encounter_list = []
24
+ entry_elements = doc.xpath(@entry_xpath)
25
+ entry_elements.each do |entry_element|
26
+ encounter = Encounter.new
27
+ extract_codes(entry_element, encounter)
28
+ extract_dates(entry_element, encounter)
29
+ extract_description(entry_element, encounter, id_map)
30
+ if @check_for_usable
31
+ encounter_list << encounter if encounter.usable?
32
+ else
33
+ encounter_list << encounter
34
+ end
35
+ extract_performer(entry_element, encounter)
36
+ extract_facility(entry_element, encounter)
37
+ extract_reason(entry_element, encounter, id_map)
38
+ extract_admission(entry_element, encounter)
39
+ end
40
+ encounter_list
41
+ end
42
+
43
+ private
44
+
45
+ def extract_performer(parent_element, encounter)
46
+ performer_element = parent_element.at_xpath("./cda:performer")
47
+ encounter.performer = import_actor(performer_element) if performer_element
48
+ end
49
+
50
+ def extract_facility(parent_element, encounter)
51
+ participant_element = parent_element.at_xpath("./cda:participant[@typeCode='LOC']/cda:participantRole[@classCode='SDLOC']")
52
+ encounter.facility = {}
53
+ if (participant_element)
54
+ encounter.facility['organizationName'] = participant_element.at_xpath("./cda:playingEntity/cda:name").try(:text)
55
+ addresses = participant_element.xpath("./cda:addr").try(:map) {|ae| import_address(ae)}
56
+ encounter.facility['addresses'] = addresses
57
+ telecoms = participant_element.xpath("./cda:telecom").try(:map) {|te| import_telecom(te)}
58
+ encounter.facility['telcoms'] = telecoms
59
+ end
60
+ end
61
+
62
+ def extract_reason(parent_element, encounter, id_map)
63
+ reason_element = parent_element.at_xpath("./cda:entryRelationship[@typeCode='RSON']/cda:act")
64
+ if reason_element
65
+ reason = Entry.new
66
+ extract_codes(reason_element, reason)
67
+ extract_description(reason_element, reason, id_map)
68
+ extract_status(reason_element, reason)
69
+ extract_dates(reason_element, reason)
70
+ encounter.reason = reason
71
+ end
72
+ end
73
+
74
+ def extract_admission(parent_element, encounter)
75
+ encounter.admit_type = extract_code(parent_element, "./cda:priorityCode")
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,61 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module C32
4
+ class ImmunizationImporter < SectionImporter
5
+
6
+ def initialize
7
+ @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.117']/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_resason_xpath = "./cda:entryRelationship[@typeCode='RSON']/cda:act[cda:templateId/@root='2.16.840.1.113883.10.20.1.27']/cda:code"
11
+ @check_for_usable = true # Pilot tools will set this to false
12
+ end
13
+
14
+ # Traverses that HITSP C32 document passed in using XPath and creates an Array of Entry
15
+ # objects based on what it finds
16
+ # @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
17
+ # will have the "cda" namespace registered to "urn:hl7-org:v3"
18
+ # measure definition
19
+ # @return [Array] will be a list of Entry objects
20
+ def create_entries(doc,id_map = {})
21
+ immunization_list = []
22
+ entry_elements = doc.xpath(@entry_xpath)
23
+ entry_elements.each do |entry_element|
24
+ immunization = Immunization.new
25
+ extract_codes(entry_element, immunization)
26
+ extract_dates(entry_element, immunization)
27
+ extract_description(entry_element, immunization, id_map)
28
+ extract_refusal(entry_element, immunization)
29
+ extract_performer(entry_element, immunization)
30
+ if @check_for_usable
31
+ immunization_list << immunization if immunization.usable?
32
+ else
33
+ immunization_list << immunization
34
+ end
35
+ end
36
+ immunization_list
37
+ end
38
+
39
+ private
40
+ def extract_refusal(parent_element, immunization)
41
+ negation_indicator = parent_element['negationInd']
42
+ unless negation_indicator.nil?
43
+ immunization.refusal_ind = negation_indicator.eql?('true')
44
+ if immunization.refusal_ind
45
+ refusal_reason_element = parent_element.at_xpath(@refusal_resason_xpath)
46
+ if refusal_reason_element
47
+ immunization.refusal_reason = {'code' => refusal_reason_element['code'],
48
+ 'codeSystem' => 'HL7 No Immunization Reason'}
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ def extract_performer(parent_element, immunization)
55
+ performer_element = parent_element.at_xpath("./cda:performer")
56
+ immunization.performer = import_actor(performer_element) if performer_element
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,138 @@
1
+ module HealthDataStandards
2
+ module Import
3
+ module C32
4
+
5
+ # TODO: Coded Product Name, Free Text Product Name, Coded Brand Name and Free Text Brand name need to be pulled out separatelty
6
+ # This would mean overriding extract_codes
7
+ # TODO: Patient Instructions needs to be implemented. Will likely be a reference to the narrative section
8
+ # TODO: Couldn't find an example medication reaction. Isn't clear to me how it should be implemented from the specs, so
9
+ # reaction is not implemented.
10
+ # TODO: Couldn't find an example dose indicator. Isn't clear to me how it should be implemented from the specs, so
11
+ # dose indicator is not implemented.
12
+ # TODO: Fill Status is not implemented. Couldn't figure out which entryRelationship it should be nested in
13
+ class MedicationImporter < SectionImporter
14
+
15
+ def initialize
16
+ @entry_xpath = "//cda:section[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.112']/cda:entry/cda:substanceAdministration"
17
+ @code_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code"
18
+ @description_xpath = "./cda:consumable/cda:manufacturedProduct/cda:manufacturedMaterial/cda:code/cda:originalText/cda:reference[@value]"
19
+
20
+ @check_for_usable = true # Pilot tools will set this to false
21
+ end
22
+
23
+ # Traverses that HITSP C32 document passed in using XPath and creates an Array of Entry
24
+ # objects based on what it finds
25
+ # @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
26
+ # will have the "cda" namespace registered to "urn:hl7-org:v3"
27
+ # measure definition
28
+ # @return [Array] will be a list of Entry objects
29
+ def create_entries(doc,id_map = {})
30
+ medication_list = []
31
+ entry_elements = doc.xpath(@entry_xpath)
32
+ entry_elements.each do |entry_element|
33
+ medication = Medication.new
34
+ extract_codes(entry_element, medication)
35
+ extract_dates(entry_element, medication)
36
+ extract_description(entry_element, medication, id_map)
37
+
38
+ if medication.description.present?
39
+ medication.free_text_sig = medication.description
40
+ end
41
+
42
+ extract_administration_timing(entry_element, medication)
43
+
44
+ medication.route = extract_code(entry_element, "./cda:routeCode")
45
+ medication.dose = extract_scalar(entry_element, "./cda:doseQuantity")
46
+ medication.site = extract_code(entry_element, "./cda:approachSiteCode", 'SNOMED-CT')
47
+
48
+ extract_dose_restriction(entry_element, medication)
49
+
50
+ medication.product_form = extract_code(entry_element, "./cda:administrationUnitCode", 'NCI Thesaurus')
51
+ medication.delivery_method = extract_code(entry_element, "./cda:code", 'SNOMED-CT')
52
+ medication.type_of_medication = extract_code(entry_element,
53
+ "./cda:entryRelationship[@typeCode='SUBJ']/cda:observation[cda:templateId/@root='2.16.840.1.113883.3.88.11.83.8.1']/cda:code", 'SNOMED-CT')
54
+ medication.indication = extract_code(entry_element,
55
+ "./cda:entryRelationship[@typeCode='RSON']/cda:observation[cda:templateId/@root='2.16.840.1.113883.10.20.1.28']/cda:code", 'SNOMED-CT')
56
+ medication.vehicle = extract_code(entry_element,
57
+ "cda:participant/cda:participantRole[cda:code/@code='412307009' and cda:code/@codeSystem='2.16.840.1.113883.6.96']/cda:playingEntity/cda:code", 'SNOMED-CT')
58
+
59
+ extract_order_information(entry_element, medication)
60
+
61
+ extract_fulfillment_history(entry_element, medication)
62
+
63
+ if @check_for_usable
64
+ medication_list << medication if medication.usable?
65
+ else
66
+ medication_list << medication_list
67
+ end
68
+ end
69
+ medication_list
70
+ end
71
+
72
+ private
73
+
74
+ def extract_fulfillment_history(parent_element, medication)
75
+ fhs = parent_element.xpath("./cda:entryRelationship/cda:supply[@moodCode='EVN']")
76
+ if fhs
77
+ fhs.each do |fh_element|
78
+ fulfillment_history = FulfillmentHistory.new
79
+ fulfillment_history.prescription_number = fh_element.at_xpath('./cda:id').try(:[], 'root')
80
+ actor_element = fh_element.at_xpath('./cda:performer')
81
+ if actor_element
82
+ fulfillment_history.provider = import_actor(actor_element)
83
+ addr_element = actor_element.at_xpath("./cda:assignedEntity/cda:addr")
84
+ if addr_element
85
+ fulfillment_history.dispensing_pharmacy_location = import_address(addr_element)
86
+ end
87
+ end
88
+ hl7_timestamp = fh_element.at_xpath('./cda:effectiveTime').try(:[], 'value')
89
+ fulfillment_history.dispense_date = HL7Helper.timestamp_to_integer(hl7_timestamp) if hl7_timestamp
90
+ fulfillment_history.quantity_dispensed = extract_scalar(fh_element, "./cda:quantity")
91
+ fulfillment_history.fill_number = fh_element.at_xpath("./cda:entryRelationship[@typeCode='COMP']/cda:sequenceNumber").try(:[], 'value').to_i
92
+ medication.fulfillmentHistory << fulfillment_history
93
+ end
94
+ end
95
+ end
96
+
97
+ def extract_order_information(parent_element, medication)
98
+ order_elements = parent_element.xpath("./cda:entryRelationship[@typeCode='REFR']/cda:supply[@moodCode='INT']")
99
+ if order_elements
100
+ order_elements.each do |order_element|
101
+ order_information = OrderInformation.new
102
+
103
+ order_information.order_number = order_element.at_xpath('./cda:id').try(:[], 'root')
104
+ order_information.fills = order_element.at_xpath('./cda:repeatNumber').try(:[], 'value').try(:to_i)
105
+ order_information.quantity_ordered = extract_scalar(order_element, "./cda:quantity")
106
+
107
+ medication.orderInformation << order_information
108
+ end
109
+ end
110
+ end
111
+
112
+ def extract_administration_timing(parent_element, medication)
113
+ administration_timing_element = parent_element.at_xpath("./cda:effectiveTime[2]")
114
+ if administration_timing_element
115
+ at = {}
116
+ if administration_timing_element['institutionSpecified']
117
+ at['institutionSpecified'] = administration_timing_element['institutionSpecified'].to_boolean
118
+ end
119
+ at['period'] = extract_scalar(administration_timing_element, "./cda:period")
120
+ if at.present?
121
+ medication.administration_timing = at
122
+ end
123
+ end
124
+ end
125
+
126
+ def extract_dose_restriction(parent_element, medication)
127
+ dre = parent_element.at_xpath("./cda:maxDoseQuantity")
128
+ if dre
129
+ dr = {}
130
+ dr['numerator'] = extract_scalar(dre, "./cda:numerator")
131
+ dr['denominator'] = extract_scalar(dre, "./cda:denominator")
132
+ medication.dose_restriction = dr
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end