health-data-standards 0.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.
@@ -0,0 +1,14 @@
1
+ require 'ostruct'
2
+
3
+ module HealthDataStandards
4
+ module Export
5
+ class RenderingContext < OpenStruct
6
+ include TemplateHelper
7
+ include ViewHelper
8
+
9
+ def my_binding
10
+ binding
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,35 @@
1
+ module HealthDataStandards
2
+ module Export
3
+ module TemplateHelper
4
+ attr_accessor :template_format
5
+
6
+ def template_root
7
+ File.join(File.dirname(__FILE__), '..', '..', '..', 'templates')
8
+ end
9
+
10
+ def template(template_name)
11
+ File.read(File.join(template_root, "#{template_name}.#{self.template_format}.erb"))
12
+ end
13
+
14
+ def partial(partial_name)
15
+ template("_#{partial_name}")
16
+ end
17
+
18
+ def render(params)
19
+ #binding.pry
20
+ erb = nil
21
+ if params[:template]
22
+ erb = template(params[:template])
23
+ elsif params[:partial]
24
+ erb = partial(params[:partial])
25
+ end
26
+ locals = params[:locals]
27
+ locals ||= {}
28
+ rendering_context = RenderingContext.new(locals)
29
+ rendering_context.template_format = self.template_format
30
+ eruby = Erubis::EscapedEruby.new(erb)
31
+ eruby.result(rendering_context.my_binding)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ module HealthDataStandards
2
+ module Export
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}>"
9
+ 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
20
+ end
21
+ end
22
+
23
+ def status_code_for(entry)
24
+ case entry.status.to_s
25
+ when 'active'
26
+ '55561003'
27
+ when 'inactive'
28
+ '73425007'
29
+ when 'resolved'
30
+ '413322009'
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,51 @@
1
+ class Entry
2
+
3
+ include Mongoid::Document
4
+
5
+ embedded_in :entry_list, polymorphic: true
6
+
7
+ field :description, type: String
8
+ field :time, type: Integer
9
+ field :start_time, type: Integer
10
+ field :end_time, type: Integer
11
+ field :status, type: Symbol
12
+ field :codes, type: Hash
13
+ field :value, type: Hash
14
+
15
+ def single_code_value?
16
+ codes.size == 1 && codes.first[1].size == 1
17
+ end
18
+
19
+ def codes_to_s
20
+ codes.map {|code_set, codes| "#{code_set}: #{codes.join(', ')}"}.join(' ')
21
+ end
22
+
23
+ def times_to_s
24
+ if start_time.present? || end_time.present?
25
+ start_string = start_time ? Time.at(start_time).to_formatted_s(:long_ordinal) : 'UNK'
26
+ end_string = end_time ? Time.at(end_time).to_formatted_s(:long_ordinal) : 'UNK'
27
+ "#{start_string} - #{end_string}"
28
+ elsif time.present?
29
+ Time.at(time).to_formatted_s(:long_ordinal)
30
+ end
31
+ end
32
+
33
+ def to_effective_time(xml)
34
+ if time.present?
35
+ xml.effectiveTime("value" => Time.at(time).utc.to_formatted_s(:number))
36
+ else
37
+ xml.effectiveTime do
38
+ if start_time.present?
39
+ xml.low("value" => Time.at(start_time).utc.to_formatted_s(:number))
40
+ else
41
+ xml.low("nullFlavor" => "UNK")
42
+ end
43
+ if end_time.present?
44
+ xml.high("value" => Time.at(end_time).utc.to_formatted_s(:number))
45
+ else
46
+ xml.high("nullFlavor" => "UNK")
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,21 @@
1
+ class Record
2
+
3
+ include Mongoid::Document
4
+
5
+ field :first, type: String
6
+ field :last, type: String
7
+ field :gender, type: String
8
+ field :birthdate, type: Integer
9
+ field :race, type: String
10
+ field :ethnicity, type: String
11
+ field :test_id, type: BSON::ObjectId
12
+
13
+ [:allergies, :care_goals, :conditions, :encounters, :immunizations, :medical_equipment,
14
+ :medications, :procedures, :results, :social_history, :vital_signs].each do |section|
15
+ embeds_many section, as: :entry_list, class_name: "Entry"
16
+ end
17
+
18
+ def over_18?
19
+ Time.at(birthdate) < Time.now.years_ago(18)
20
+ end
21
+ end
@@ -0,0 +1,57 @@
1
+ <component>
2
+ <!--Allergies/Reactions-->
3
+ <section>
4
+ <templateId root="2.16.840.1.113883.3.88.11.83.102" assigningAuthorityName="HITSP/C83"/>
5
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.3.13" assigningAuthorityName="IHE PCC"/>
6
+ <templateId root="2.16.840.1.113883.10.20.1.2" assigningAuthorityName="HL7 CCD"/>
7
+ <!--Allergies/Reactions section template-->
8
+ <code code="48765-2" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC" displayName="Allergies"/>
9
+ <title>Allergies and Adverse Reactions</title>
10
+ <%== render :partial => 'narrative_block', :locals => {:entries => entries, :section => 'allergies'} %>
11
+ <% entries.each_with_index do |entry, i| -%>
12
+ <entry typeCode="DRIV">
13
+ <act classCode="ACT" moodCode="EVN">
14
+ <templateId root="2.16.840.1.113883.3.88.11.83.6"/>
15
+ <templateId root="2.16.840.1.113883.10.20.1.27"/>
16
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.4.5.3"/>
17
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.4.5.1"/>
18
+ <!--Allergy act template -->
19
+ <id root="<%= UUID.generate %>"/>
20
+ <code nullFlavor="NA"/>
21
+ <statusCode code="active"/>
22
+ <effectiveTime>
23
+ <low value="<%= Time.at(entry.time).utc.to_formatted_s(:number) %>"/>
24
+ </effectiveTime>
25
+ <entryRelationship typeCode="SUBJ" inversionInd="false">
26
+ <observation classCode="OBS" moodCode="EVN">
27
+ <templateId root="2.16.840.1.113883.10.20.1.18"/>
28
+ <templateId root="2.16.840.1.113883.10.20.1.28"/>
29
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.4.6"/>
30
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.4.5"/>
31
+ <id root="<%= UUID.generate %>"/>
32
+ <code code="416098002" codeSystem="2.16.840.1.113883.6.96" displayName="drug allergy" codeSystemName="SNOMED CT">
33
+ <originalText><reference value="#allergies-desc-<%= i %>"/></originalText>
34
+ </code>
35
+ <text>
36
+ <reference value="#allergies-desc-<%= i %>"/>
37
+ </text>
38
+ <statusCode code="completed"/>
39
+ <effectiveTime>
40
+ <low value="<%= Time.at(entry.time).utc.to_formatted_s(:number) %>"/>
41
+ </effectiveTime>
42
+ <value xsi:type="CD" nullFlavor="UNK"/>
43
+ <participant typeCode="CSM">
44
+ <participantRole classCode="MANU">
45
+ <playingEntity classCode="MMAT">
46
+ <%== render :partial => 'code_with_reference', :locals => {:entry => entry, :i => i, :section => 'allergies'} %>
47
+ <name><%= entry.description %></name>
48
+ </playingEntity>
49
+ </participantRole>
50
+ </participant>
51
+ </observation>
52
+ </entryRelationship>
53
+ </act>
54
+ </entry>
55
+ <% end -%>
56
+ </section>
57
+ </component>
@@ -0,0 +1,24 @@
1
+ <component>
2
+ <!--Plan of Care-->
3
+ <section>
4
+ <templateId root="2.16.840.1.113883.3.88.11.83.124" assigningAuthorityName="HITSP/C83"/>
5
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.3.31" assigningAuthorityName="IHE PCC"/>
6
+ <templateId root="2.16.840.1.113883.10.20.2.7" assigningAuthorityName="HL7 CCD"/>
7
+ <templateId root="2.16.840.1.113883.10.20.1.10" assigningAuthorityName="HL7 CCD"/>
8
+ <!--Plan of Care section template-->
9
+ <code code="18776-5" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC" displayName="Treatment plan"/>
10
+ <%== render :partial => 'narrative_block', :locals => {:entries => entries, :section => 'plan_of_care'} %>
11
+ <% entries.each do |entry| -%>
12
+ <entry typeCode="DRIV">
13
+ <observation classCode="OBS" moodCode="RQO">
14
+ <templateId root="2.16.840.1.113883.10.20.1.25"/>
15
+ <!-- Plan of Activity activity template -->
16
+ <id root="<%= UUID.generate %>"/>
17
+ <%== code_display(entry) %>
18
+ <statusCode code="new"/>
19
+ <effectiveTime value="<%= Time.at(entry.time).utc.to_formatted_s(:number) %>"/>
20
+ </observation>
21
+ </entry>
22
+ <% end -%>
23
+ </section>
24
+ </component>
@@ -0,0 +1,8 @@
1
+ <% if entry.single_code_value?
2
+ code = entry.codes.first[1].first
3
+ code_system_oid = QME::Importer::CodeSystemHelper.oid_for_code_system(entry.codes.first[0])
4
+ -%>
5
+ <code code="<%= code %>" codeSystem="<%= code_system_oid %>">
6
+ <originalText><reference value="#<%= section %>-desc-<%= i %>"/></originalText>
7
+ </code>
8
+ <% end -%>
@@ -0,0 +1,61 @@
1
+ <component>
2
+ <!--Problems-->
3
+ <section>
4
+ <templateId root="2.16.840.1.113883.3.88.11.83.103" assigningAuthorityName="HITSP/C83"/>
5
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.3.6" assigningAuthorityName="IHE PCC"/>
6
+ <templateId root="2.16.840.1.113883.10.20.1.11" assigningAuthorityName="HL7 CCD"/>
7
+ <!--Problems section template-->
8
+ <code code="11450-4" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC" displayName="Problem list"/>
9
+ <title>Problems</title>
10
+ <%== render :partial => 'narrative_block', :locals => {:entries => entries, :section => 'conditions'} %>
11
+ <% entries.each_with_index do |entry, i| -%>
12
+ <entry typeCode="DRIV">
13
+ <act classCode="ACT" moodCode="EVN">
14
+ <templateId root="2.16.840.1.113883.3.88.11.83.7" assigningAuthorityName="HITSP C83"/>
15
+ <templateId root="2.16.840.1.113883.10.20.1.27"/>
16
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.4.5.1" assigningAuthorityName="IHE PCC"/>
17
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.4.5.2" assigningAuthorityName="IHE PCC"/>
18
+ <!-- Problem act template -->
19
+ <id root="<%= UUID.generate %>"/>
20
+ <code nullFlavor="NA"/>
21
+ <% if entry.status.eql? 'resolved' -%>
22
+ <statusCode code="completed"/>
23
+ <% else -%>
24
+ <statusCode code="active"/>
25
+ <% end -%>
26
+ <effectiveTime>
27
+ <low value="<%= Time.at(entry.time).utc.to_formatted_s(:number) %>"/>
28
+ </effectiveTime>
29
+ <entryRelationship typeCode="SUBJ" inversionInd="false">
30
+ <observation classCode="OBS" moodCode="EVN">
31
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.4.5" assigningAuthorityName="IHE PCC"/>
32
+ <templateId root="2.16.840.1.113883.10.20.1.28" assigningAuthorityName="CCD"/>
33
+ <!--Problem observation template - NOT episode template-->
34
+ <id root="<%= UUID.generate %>"/>
35
+ <code code="64572001" displayName="Condition" codeSystem="2.16.840.1.113883.6.96" codeSystemName="SNOMED-CT"/>
36
+ <text>
37
+ <reference value="#conditions-desc-<%= i %>"/>
38
+ </text>
39
+ <statusCode code="completed"/>
40
+ <effectiveTime>
41
+ <low value="<%= Time.at(entry.time).utc.to_formatted_s(:number) %>"/>
42
+ </effectiveTime>
43
+ <%== code_display(entry, 'value', 'xsi:type="CD"') %>
44
+ <% if entry.status -%>
45
+ <entryRelationship typeCode="REFR">
46
+ <observation classCode="OBS" moodCode="EVN">
47
+ <templateId root="2.16.840.1.113883.10.20.1.50"/>
48
+ <!-- Problem status observation template -->
49
+ <code code="33999-4" codeSystem="2.16.840.1.113883.6.1" displayName="Status"/>
50
+ <statusCode code="completed"/>
51
+ <value xsi:type="CE" code="<%= status_code_for(entry) %>" codeSystem="2.16.840.1.113883.6.96"/>
52
+ </observation>
53
+ </entryRelationship>
54
+ <% end -%>
55
+ </observation>
56
+ </entryRelationship>
57
+ </act>
58
+ </entry>
59
+ <% end -%>
60
+ </section>
61
+ </component>
@@ -0,0 +1,28 @@
1
+ <component>
2
+ <!--Encounters-->
3
+ <section>
4
+ <templateId root="2.16.840.1.113883.3.88.11.83.127" assigningAuthorityName="HITSP/C83"/>
5
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.1.5.3.3" assigningAuthorityName="IHE PCC"/>
6
+ <templateId root="2.16.840.1.113883.10.20.1.3" assigningAuthorityName="HL7 CCD"/>
7
+ <!--Encounters section template-->
8
+ <code code="46240-8" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC" displayName="History of encounters"/>
9
+ <title>Encounters</title>
10
+ <%== render :partial => 'narrative_block', :locals => {:entries => entries, :section => 'encounters'} %>
11
+ <% entries.each_with_index do |entry, i| -%>
12
+ <entry typeCode="DRIV">
13
+ <encounter classCode="ENC" moodCode="EVN">
14
+ <templateId root="2.16.840.1.113883.3.88.11.83.16" assigningAuthorityName="HITSP C83"/>
15
+ <templateId root="2.16.840.1.113883.10.20.1.21" assigningAuthorityName="CCD"/>
16
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.4.14" assigningAuthorityName="IHE PCC"/>
17
+ <!-- Encounter activity template -->
18
+ <id root="<%= UUID.generate %>"/>
19
+ <%== render :partial => 'code_with_reference', :locals => {:entry => entry, :i => i, :section => 'encounters'} %>
20
+ <text>
21
+ <reference value="#encounters-desc-<%= i %>"/>
22
+ </text>
23
+ <effectiveTime value="<%= Time.at(entry.time).utc.to_formatted_s(:number) %>"/>
24
+ </encounter>
25
+ </entry>
26
+ <% end -%>
27
+ </section>
28
+ </component>
@@ -0,0 +1,41 @@
1
+ <component>
2
+ <!--Immunizations-->
3
+ <section>
4
+ <templateId root="2.16.840.1.113883.3.88.11.83.117" assigningAuthorityName="HITSP/C83"/>
5
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.3.23" assigningAuthorityName="IHE PCC"/>
6
+ <templateId root="2.16.840.1.113883.10.20.1.6" assigningAuthorityName="HL7 CCD"/>
7
+ <!--Immunizations section template-->
8
+ <code code="11369-6" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC" displayName="History of immunizations"/>
9
+ <title>Immunizations</title>
10
+ <%== render :partial => 'narrative_block', :locals => {:entries => entries, :section => 'immunizations'} %>
11
+ <% entries.each_with_index do |entry, i| -%>
12
+ <entry typeCode="DRIV">
13
+ <substanceAdministration classCode="SBADM" moodCode="EVN" negationInd="false">
14
+ <templateId root="2.16.840.1.113883.10.20.1.24"/>
15
+ <templateId root="2.16.840.1.113883.3.88.11.83.13" />
16
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.4.12"/>
17
+ <!-- Medication activity template -->
18
+ <id root="<%= UUID.generate %>"/>
19
+ <code code='IMMUNIZ' codeSystem='2.16.840.1.113883.5.4' codeSystemName='ActCode'/>
20
+ <text>
21
+ <reference value="#immunizations-desc-<%= i %>"/>
22
+ </text>
23
+ <statusCode code="completed"/>
24
+ <effectiveTime value="<%= Time.at(entry.time).utc.to_formatted_s(:number) %>"/>
25
+ <doseQuantity nullFlavor="UNK"/>
26
+ <consumable>
27
+ <manufacturedProduct>
28
+ <templateId root="2.16.840.1.113883.10.20.1.53"/>
29
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.4.7.2"/>
30
+ <!-- Product template -->
31
+ <manufacturedMaterial>
32
+ <%== render :partial => 'code_with_reference', :locals => {:entry => entry, :i => i, :section => 'immunizations'} %>
33
+ <name><%= entry.description %></name>
34
+ </manufacturedMaterial>
35
+ </manufacturedProduct>
36
+ </consumable>
37
+ </substanceAdministration>
38
+ </entry>
39
+ <% end -%>
40
+ </section>
41
+ </component>
@@ -0,0 +1,34 @@
1
+ <component>
2
+ <!--Medical Equipment - Not C32-->
3
+ <section>
4
+ <templateId root="2.16.840.1.113883.3.88.11.83.128" assigningAuthorityName="HITSP/C83"/>
5
+ <templateId root="2.16.840.1.113883.10.20.1.7" assigningAuthorityName="CCD"/>
6
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.1.5.3.5" assigningAuthorityName="IHE PCC"/>
7
+ <!-- Medical equipment section template -->
8
+ <code code="46264-8" codeSystem="2.16.840.1.113883.6.1"/>
9
+ <title>Medical Equipment</title>
10
+ <%== render :partial => 'narrative_block', :locals => {:entries => entries, :section => 'medical_equipment'} %>
11
+ <% entries.each_with_index do |entry, i| -%>
12
+ <entry typeCode="DRIV">
13
+ <supply classCode="SPLY" moodCode="EVN">
14
+ <templateId root="2.16.840.1.113883.10.20.1.34"/>
15
+ <!-- Supply activity template -->
16
+ <id root="<%= UUID.generate %>"/>
17
+ <statusCode code="completed"/>
18
+ <effectiveTime value="<%= Time.at(entry.time).utc.to_formatted_s(:number) %>"/>
19
+ <participant typeCode="DEV">
20
+ <participantRole classCode="MANU">
21
+ <templateId root="2.16.840.1.113883.10.20.1.52"/>
22
+ <!-- Product instance template -->
23
+ <addr/>
24
+ <telecom/>
25
+ <playingDevice>
26
+ <%== code_display(entry) %>
27
+ </playingDevice>
28
+ </participantRole>
29
+ </participant>
30
+ </supply>
31
+ </entry>
32
+ <% end -%>
33
+ </section>
34
+ </component>
@@ -0,0 +1,40 @@
1
+ <component>
2
+ <!--Medications-->
3
+ <section>
4
+ <templateId root="2.16.840.1.113883.10.20.1.8" assigningAuthorityName="HL7 SDTC CCD"/>
5
+ <templateId root="2.16.840.1.113883.3.88.11.83.112" assigningAuthorityName="HITSP"/>
6
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.3.19" assigningAuthorityName="IHE"/>
7
+ <code code="10160-0" displayName="History of medication use" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC"/>
8
+ <title>Medications - Prescription and Non-Prescription</title>
9
+ <%== render :partial => 'narrative_block', :locals => {:entries => entries, :section => 'medications'} %>
10
+ <% entries.each_with_index do |entry, i| -%>
11
+ <entry>
12
+ <!--CCD Medication activity - Required-->
13
+ <substanceAdministration classCode="SBADM" moodCode="EVN">
14
+ <templateId root="2.16.840.1.113883.10.20.1.24" assigningAuthorityName="HL7 SDTC CCD"/>
15
+ <templateId root="2.16.840.1.113883.3.88.11.83.8"/>
16
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.4.7"/>
17
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.4.7.1"/>
18
+ <id root="<%= UUID.generate %>"/>
19
+ <statusCode code="completed"/>
20
+ <effectiveTime xsi:type="IVL_TS">
21
+ <low value="<%= Time.at(entry.time).utc.to_formatted_s(:number) %>"/>
22
+ <high nullFlavor="UNK"/>
23
+ </effectiveTime>
24
+ <consumable>
25
+ <!--CCD Product - Required-->
26
+ <manufacturedProduct classCode="MANU">
27
+ <templateId root="2.16.840.1.113883.10.20.1.53" assigningAuthorityName="HL7 SDTC CCD"/>
28
+ <templateId root="2.16.840.1.113883.3.88.11.83.8.2"/>
29
+ <templateId root="1.3.6.1.4.1.19376.1.5.3.1.4.7.2"/>
30
+ <manufacturedMaterial>
31
+ <%== render :partial => 'code_with_reference', :locals => {:entry => entry, :i => i, :section => 'medications'} %>
32
+ <name><%= entry.description %></name>
33
+ </manufacturedMaterial>
34
+ </manufacturedProduct>
35
+ </consumable>
36
+ </substanceAdministration>
37
+ </entry>
38
+ <% end -%>
39
+ </section>
40
+ </component>