Skip to content
Open

Imi #269

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
7400665
Basic runner script
psalaets Oct 18, 2022
38c4e82
Tests for different numbers of indications
psalaets Oct 18, 2022
fd91ea7
Merge branch 'immunization-indications'
psalaets Oct 20, 2022
74a6571
Correct comment
psalaets Oct 21, 2022
bb4e945
Include immunization reaction
psalaets Oct 21, 2022
eb61670
intial changes to social history for tobacco use
cbleslie Oct 24, 2022
0a5593a
Merge pull request #1 from psalaets/immunization-reaction-observation
psalaets Oct 24, 2022
cbd7aed
Merge remote-tracking branch 'origin/master' into feature/tobacco-use
cbleslie Oct 24, 2022
63bbd09
medication addition test
Oct 24, 2022
5cba59c
for paul to check out
cbleslie Oct 24, 2022
ff6a7c8
getting closer
cbleslie Oct 24, 2022
c8f7c1c
IMI Comments
Oct 24, 2022
41ddb5e
var-names
Oct 25, 2022
8479d0c
xml
Oct 25, 2022
503acda
xml-changes
Oct 25, 2022
23b4e55
more-xml-changes
Oct 25, 2022
4919b45
figure stuff out still
cbleslie Oct 25, 2022
4dc7e89
Adding support for a few more social history types
psalaets Oct 25, 2022
86cc236
Merge pull request #2 from psalaets/feature/tobacco-use
psalaets Oct 25, 2022
7f7b81d
nutrition
Oct 26, 2022
1c916d3
initial
Oct 26, 2022
bb1ff4a
ready for review
cbleslie Oct 26, 2022
43bd892
cleaning up
cbleslie Oct 26, 2022
2c2e6e6
Nutrition clean up and some really simple tests
psalaets Oct 26, 2022
edb7f54
Revert "IMI Comments"
psalaets Oct 26, 2022
7260e3b
Revert "medication addition test"
psalaets Oct 26, 2022
9bed115
Merge pull request #3 from psalaets/nutrition
psalaets Oct 26, 2022
2bb9a00
merging master
cbleslie Oct 26, 2022
cbabe48
Change Review of Systems from array to object and add a few basic tests
psalaets Oct 26, 2022
00e791c
Merge pull request #4 from psalaets/feature/review-of-systems
psalaets Oct 26, 2022
7ce6bd3
Parse indictions inside a Plan of Treatment section, if any
psalaets Oct 27, 2022
d7b223b
Merge pull request #5 from psalaets/feature/plan-of-treatment-indication
psalaets Oct 27, 2022
5c58965
adding author
cbleslie Oct 27, 2022
103a098
Reword
psalaets Oct 27, 2022
2afbf58
cleanup
cbleslie Oct 27, 2022
02f23a7
Merge branch 'feature/results-author' of github.com:psalaets/blue-but…
cbleslie Oct 27, 2022
2b55368
Merge pull request #6 from psalaets/feature/results-author
psalaets Oct 27, 2022
d516a6c
Add plan of treatment / nutrition rec
psalaets Oct 27, 2022
397fa1b
Adding plan of treatment / nutrition recommendation
psalaets Oct 27, 2022
04b5294
Update basic test for nutrition rec
psalaets Oct 27, 2022
a9d3fdd
initial reaction observation
cbleslie Oct 28, 2022
15a367f
Adding tests.
cbleslie Oct 28, 2022
e6297c0
partial
Nov 4, 2022
951892d
fix medication section with immunizations
Nov 7, 2022
33636ce
add supporting files
Nov 7, 2022
49fee71
fix medication section with immunizations
Nov 7, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions lib/nutrition.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
module.exports = { // this needs work or the section needs or both
"id": "nutrition",
"type": "object",
"properties": {
/* "date_time": {
"$ref": "cda_date"
}, */
/* "identifiers": {
"type": "string",
"item": {
"$ref": "cda_id"
},
}, */
/* "value": {
"type": "string"
}, */
/* "value": {
"type": "string"
}, */
"code": {
"type": "string"
},
"title": {
"type": "string"
},
"text": {
"type": "string"
},
"entry": {
"type": "array",
"observation": {
"type": "object",
"properties": {
"id": {
"type": "array"
},
"statusCode": {
"type": "string"
},
"code": {
"type": "string"
},
"templateId": {
"type": "string"
},
"title": {
"type": "string"
},
"effectiveTime": {
"type": "string"
},
"value": {
"type": "string"
},
"entryRelationship": {
"type": "array",
"nutritionAssessment": {
"type": "object",
"properties": {
/* "identifiers": {
"type": "string",
"item": {
"$ref": "cda_id"
},
}, */
"templateId": {
"type": "string"
},
"id": {
"type": "array"
},
/* "classCode": {
"type": "string"
},
"moodCode": {
"type": "string"
}, */
"code": {
"type": "string"
},
/* "codeSystem": {
"type": "string"
}, */
"statusCode": {
"type": "string"
},
"effectiveTime": {
"$ref": "cda_date"
},
"value": {
"type": "string"
},
"authorParticipation": {
"type": "object",
"properties": {
"templateId": {
"type": "string"
},
"time": {
"$ref": "cda_date"
},
"assignedAuthor": {
"type": "string",
"id": {
"type": "string"
},
"code": {
"type": "string"
},
"assignedPerson": {
"type": "string"
},
"name": {
"type": "array"
},
"representedOrganization": {
"type": "string",
"id": {
"type": "array"
},
"name": {
"type": "array"
},
"telecom": {
"type": "array"
},
"addr": {
"type": "array"
}
}
}
}
}
}
}
}
}
}
}
},
"additionalProperties": false,
"minProperties": 1,
// "required": [
// "value"
// ]
};
8 changes: 7 additions & 1 deletion lib/parser/ccda/ccd.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ var exportCCD = function (version) {
var hospital_discharge_instructions_section = require("./sections/hospital_discharge_instructions").hospital_discharge_instructions_section(version)[0];
var hospital_discharge_medications_section = require("./sections/hospital_discharge_medications").hospital_discharge_medications_section(version)[0];
var functional_status_section = require("./sections/functional_status").functionalStatusSection(version)[0];
var review_of_systems_section = require("./sections/review_of_systems").reviewOfSystemsSection(version)[0];
var nutrition_section = require("./sections/nutrition").nutritionSection(version);
var plan_of_treatment_section = require("./sections/plan_of_treatment").planOfTreatmentSection(version);

return component.define("CCD")
.fields([
Expand All @@ -41,7 +44,10 @@ var exportCCD = function (version) {
["reason_for_referral", "0..1", reason_for_referral_section.xpath(), reason_for_referral_section],
["hospital_discharge_instructions", "0..1", hospital_discharge_instructions_section.xpath(), hospital_discharge_instructions_section],
["hospital_discharge_medications", "0..1", hospital_discharge_medications_section.xpath(), hospital_discharge_medications_section],
["functional_statuses", "0..1", functional_status_section.xpath(), functional_status_section]
["functional_statuses", "0..1", functional_status_section.xpath(), functional_status_section],
["nutrition_observations", "0..1", nutrition_section.xpath(), nutrition_section],
["review_of_systems", "0..1", review_of_systems_section.xpath(), review_of_systems_section],
["plan_of_treatment", "0..1", plan_of_treatment_section.xpath(), plan_of_treatment_section]
]);
};

Expand Down
27 changes: 27 additions & 0 deletions lib/parser/ccda/sections/immunizations.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,31 @@ var exportImmunizationsSection = function (version) {
["manufacturer", "0..1", "h:manufacturerOrganization/h:name/text()"],
]);

var Indication = component.define("Indication")
.fields([
["identifiers", "0..*", "h:id", shared.Identifier],
["code", "0..1", "h:code", shared.ConceptDescriptor],
["date_time", "0..1", "h:effectiveTime", shared.EffectiveTime],
["value", "0..1", "h:value", shared.ConceptDescriptor]
]);

var ImmunizationSeverityObservation = component.define("immunizationSeverityObservation")
.fields([
["code", "0..1", "h:value", shared.ConceptDescriptor],
["interpretation", "0..1", "h:interpretationCode", shared.ConceptDescriptor]
]);

var ImmunizationReaction = component.define("immunizationReaction");
ImmunizationReaction.templateRoot(["2.16.840.1.113883.10.20.22.4.9"]);
ImmunizationReaction.fields([
["identifiers", "0..*", "h:id", shared.Identifier],
["date_time", "1..1", "h:effectiveTime", shared.EffectiveTime],
["reaction", "1..1", "h:value", shared.ConceptDescriptor],
["free_text_reaction", "0..1", "h:text", shared.TextWithReference],
["severity", "0..1", "h:entryRelationship/h:observation", ImmunizationSeverityObservation]
]);
ImmunizationReaction.cleanupStep(cleanup.promoteFreeTextIfNoReaction);

var ImmunizationActivity = component.define("ImmunizationActivity")
.templateRoot([clinicalStatementsIDs.ImmunizationActivity, clinicalStatementsIDs.MedicationActivity])
.fields([
Expand All @@ -63,6 +88,8 @@ var exportImmunizationsSection = function (version) {
["performer", "0..1", "h:performer/h:assignedEntity", shared.assignedEntity],
["instructions", "0..1", "h:entryRelationship[@typeCode='SUBJ']/h:act", ImmunizationInstructions],
["refusal_reason", "0..1", "h:entryRelationship/h:observation/h:code/@code", shared.SimpleCode("2.16.840.1.113883.5.8")],
["indications", "0..*", "h:entryRelationship[@typeCode='RSON']/h:observation", Indication],
["reaction", "0..1", "h:entryRelationship[@typeCode='CAUS']/h:observation", ImmunizationReaction],
]).cleanupStep(function () { // Quick and dirty fix for when refusal_reason catches other observations in Vitera.
if (this.js) { // Refusal reason should use the template id
if (this.js.refusal_reason && (!_.get(this, "js.refusal_reason.js"))) {
Expand Down
64 changes: 58 additions & 6 deletions lib/parser/ccda/sections/medications.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,23 @@ var exportMedicationsSection = function (version) {
source: http://wiki.siframework.org/CDA+-+Medications+Section

*/

var MedicationSeverityObservation = component.define("immunizationSeverityObservation")
.fields([
["code", "0..1", "h:value", shared.ConceptDescriptor],
["interpretation", "0..1", "h:interpretationCode", shared.ConceptDescriptor]
]);
var MedicationReaction = component.define("medicationReaction")
.templateRoot(["2.16.840.1.113883.10.20.22.4.9"])
.fields([
["identifiers", "0..*", "h:id", shared.Identifier],
["date_time", "1..1", "h:effectiveTime", shared.EffectiveTime],
["reaction", "1..1", "h:value", shared.ConceptDescriptor],
["free_text_reaction", "0..1", "h:text", shared.TextWithReference],
["severity", "0..1", "h:entryRelationship/h:observation", MedicationSeverityObservation]
])
.cleanupStep(cleanup.promoteFreeTextIfNoReaction);

var MedicationInterval = component.define("MedicationInterval")
.fields([
["phase", "0..1", "./h:phase", shared.EffectiveTime],
Expand Down Expand Up @@ -85,12 +102,29 @@ var exportMedicationsSection = function (version) {
// * ccda-r1.1 (LATEST VERSION) *
// ***************************************************************************

var immunizationMedicationInformation;
var medicationInformation;
var medicationSupplyOrder;
var medicationActivity;
var medicationsSection;
var manufacturedMaterial;

if (version === "") {

manufacturedMaterial = component.define("manufacturedMaterial")
.fields([
["code", "1..1", "h:manufacturedMaterial/h:code "],
["translation", "0..*", "h:manufacturedMaterial/h:translation"],
["lotNumberText", "0..*", "h:manufacturedMaterial/h:lotNumberText"],
["manufacturerOrganization", "0..1", "h:manufacturerOrganization"],
]);

immunizationMedicationInformation = component.define("immunizationMedicationInformation")
.templateRoot("2.16.840.1.113883.10.20.22.4.54")
.fields([
["id", "0..*", "h:id"],
["manufacturedMaterial", "1..1", "h:manufacturedMaterial", manufacturedMaterial],
]);
medicationInformation = component.define("medicationInformation")
.templateRoot("2.16.840.1.113883.10.20.22.4.23")
.fields([
Expand Down Expand Up @@ -133,7 +167,8 @@ var exportMedicationsSection = function (version) {
["identifiers", "0..*", "h:id", shared.Identifier],
["performer", "0..1", "h:performer", MedicationPerformer],
["supply", "0..1", "h:entryRelationship[@typeCode='REFR']/h:supply", medicationSupplyOrder],
["product", "0..1", "h:product/h:manufacturedProduct", medicationInformation]
["product", "0..1", "h:product/h:manufacturedProduct", medicationInformation],
["product", "0..1", "h:product/h:manufacturedProduct", immunizationMedicationInformation]
]);

medicationActivity = component.define("medicationActivity")
Expand All @@ -144,6 +179,7 @@ var exportMedicationsSection = function (version) {
["sig", "0..1", "h:text", shared.TextWithReference],
["product", "1..1", "h:consumable/h:manufacturedProduct", medicationInformation],
["supply", "0..1", "h:entryRelationship[@typeCode='REFR']/h:supply", medicationSupplyOrder],
["reactions", "0..*", "h:entryRelationship[@typeCode='CAUS']/h:observation", MedicationReaction],
["administration", "0..1", "../h:substanceAdministration", MedicationAdministration],
["performer", "0..1", "h:performer", MedicationPerformer],
["drug_vehicle", "0..1", "h:participant[@typeCode='CSM']/h:participantRole/h:playingEntity[@classCode='MMAT']/h:code", shared.ConceptDescriptor],
Expand Down Expand Up @@ -192,11 +228,12 @@ var exportMedicationsSection = function (version) {

// ignore negationInd medications

medicationsSection = component.define("medicationsSection");
medicationsSection.templateRoot(["2.16.840.1.113883.10.20.22.2.1", "2.16.840.1.113883.10.20.22.2.1.1"]);
medicationsSection.fields([
["medications", "0..*", medicationActivity.xpath(), medicationActivity]
]);
medicationsSection = component.define("medicationsSection")
.templateRoot(["2.16.840.1.113883.10.20.22.2.1", "2.16.840.1.113883.10.20.22.2.1.1"])
.fields([
["medications", "0..*", medicationActivity.xpath(), medicationActivity]// seems to include all of activity and everything defined in it
]);
// console.log(medicationsSection)
medicationsSection.cleanupStep(cleanup.replaceWithField('medications'));
return [medicationsSection, medicationActivity];

Expand All @@ -205,6 +242,21 @@ var exportMedicationsSection = function (version) {
// ***************************************************************************
} else {

manufacturedMaterial = component.define("manufacturedMaterial")
.fields([
["code", "1..1", "h:manufacturedMaterial/h:code "],
["translation", "0..*", "h:manufacturedMaterial/h:translation"],
["lotNumberText", "0..*", "h:manufacturedMaterial/h:lotNumberText"],
["lotNumberText", "0..1", "h:lotNumberText"],
]);

immunizationMedicationInformation = component.define("immunizationMedicationInformation")
.templateRoot("2.16.840.1.113883.10.20.22.4.54")
.fields([
["id", "0..*", "h:id"],
["manufacturedMaterial", "1..1", "h:manufacturedMaterial", manufacturedMaterial],
["manufacturerOrganization", "1..1", "h:manufacturerOrganization"],
]);
medicationInformation = component.define("medicationInformation")
.templateRoot("2.16.840.1.113883.10.20.1.53")
.fields([
Expand Down
37 changes: 37 additions & 0 deletions lib/parser/ccda/sections/nutrition.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
var shared = require("../shared");
var component = require("@amida-tech/blue-button-xml").component.withNullFlavor();
var cleanup = require("../cleanup");

var exportNutritionSection = function () {
var nutritionalStatusObservation;
var nutritionSection;
var nutritionAssessment;

nutritionAssessment = component.define("nutritionAssessment")
.templateRoot("2.16.840.1.113883.10.20.22.4.138")
.fields([
["identifiers", "1..*", "h:id", shared.Identifier],
["date_time", "1..1", "h:effectiveTime", shared.EffectiveTime],
["value", "1..1", "h:value[@xsi:type='CD']/@displayName"],
]);

nutritionalStatusObservation = component.define("nutritionalStatusObservation")
.templateRoot("2.16.840.1.113883.10.20.22.4.124")
.fields([
["identifiers", "1..*", "h:id", shared.Identifier],
["date_time", "1..1", "h:effectiveTime", shared.EffectiveTime],
["value", "1..1", "h:value[@xsi:type='CD']/@displayName"],
["assessments", "1..*", "h:entryRelationship/h:observation", nutritionAssessment],
]);

nutritionSection = component.define("nutritionSection")
.templateRoot("2.16.840.1.113883.10.20.22.2.57")
.fields([
["observations", "0..*", "h:entry/h:observation", nutritionalStatusObservation],
]);

nutritionSection.cleanupStep(cleanup.replaceWithField('observations'));
return nutritionSection;
};

exports.nutritionSection = exportNutritionSection;
32 changes: 32 additions & 0 deletions lib/parser/ccda/sections/plan_of_treatment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
var shared = require("../shared");
var component = require("@amida-tech/blue-button-xml").component.withNullFlavor();

var exportPlanOfTreatmentSection = function() {
var planOfTreatmentNutritionRecommendation = component.define('planOfTreatmentNutritionRecommendation');
planOfTreatmentNutritionRecommendation.templateRoot(["2.16.840.1.113883.10.20.22.4.130"]);
planOfTreatmentNutritionRecommendation.fields([
["identifiers", "0..*", "h:id", shared.Identifier],
["code", "1..1", "h:code", shared.ConceptDescriptor],
["date_time", "0..1", "h:effectiveTime", shared.EffectiveTime]
]);

var planOfTreatmentIndication = component.define("planOfTreatmentIndication")
planOfTreatmentIndication.templateRoot(["2.16.840.1.113883.10.20.22.4.19"])
planOfTreatmentIndication.fields([
["identifiers", "0..*", "h:id", shared.Identifier],
["code", "0..1", "h:code", shared.ConceptDescriptor],
["date_time", "0..1", "h:effectiveTime", shared.EffectiveTime],
["value", "0..1", "h:value", shared.ConceptDescriptor]
]);

var planOfTreatmentSection = component.define("planOfTreatmentSection");
planOfTreatmentSection.templateRoot(["2.16.840.1.113883.10.20.22.2.10"]);
planOfTreatmentSection.fields([
["indications", "0..*", planOfTreatmentIndication.xpath(), planOfTreatmentIndication],
["nutrition_recommendations", "0..*", planOfTreatmentNutritionRecommendation.xpath(), planOfTreatmentNutritionRecommendation]
])

return planOfTreatmentSection;
};

exports.planOfTreatmentSection = exportPlanOfTreatmentSection;
Loading