Skip to content

Commit b3f9808

Browse files
mickohanlon23julianxcarter
authored andcommitted
Core functionality for adverse events CSV extractor
1 parent e4719ef commit b3f9808

File tree

6 files changed

+196
-0
lines changed

6 files changed

+196
-0
lines changed

src/client/MCODEClient.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const { BaseClient } = require('./BaseClient');
22
const {
3+
CSVAdverseEventExtractor,
34
CSVCancerDiseaseStatusExtractor,
45
CSVCancerRelatedMedicationExtractor,
56
CSVClinicalTrialInformationExtractor,
@@ -25,6 +26,7 @@ class MCODEClient extends BaseClient {
2526
constructor({ extractors, commonExtractorArgs, webServiceAuthConfig }) {
2627
super();
2728
this.registerExtractors(
29+
CSVAdverseEventExtractor,
2830
CSVCancerDiseaseStatusExtractor,
2931
CSVCancerRelatedMedicationExtractor,
3032
CSVClinicalTrialInformationExtractor,
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const path = require('path');
2+
const { CSVModule } = require('../modules');
3+
const { generatemCODEResources } = require('../templates');
4+
const { Extractor } = require('./Extractor');
5+
const logger = require('../helpers/logger');
6+
const { formatDateTime } = require('../helpers/dateUtils');
7+
8+
// Formats data to be passed into template-friendly format
9+
function formatData(adverseEventData) {
10+
logger.debug('Reformatting adverse event data from CSV into template format');
11+
return adverseEventData.map((data) => {
12+
const {
13+
mrn, adverseEventId, adverseEventCode, adverseEventCodeSystem, adverseEventDisplayText, suspectedCauseId, suspectedCauseType, seriousness, seriousnessCodeSystem, seriousnessDisplayText,
14+
category, categoryCodeSystem, categoryDisplayText, severity, actuality, studyId, effectiveDate, recordedDate,
15+
} = data;
16+
17+
if (!(mrn && adverseEventCode && effectiveDate)) {
18+
throw new Error('The adverse event is missing an expected attribute. Adverse event code, mrn, and effective date are all required.');
19+
}
20+
return {
21+
id: adverseEventId,
22+
subjectId: mrn,
23+
code: adverseEventCode,
24+
system: adverseEventCodeSystem,
25+
display: adverseEventDisplayText,
26+
suspectedCauseId,
27+
suspectedCauseType,
28+
seriousnessCode: seriousness,
29+
seriousnessCodeSystem,
30+
seriousnessDisplayText,
31+
categoryCode: category,
32+
categoryCodeSystem,
33+
categoryDisplayText,
34+
severity,
35+
actuality,
36+
studyId,
37+
effectiveDateTime: formatDateTime(effectiveDate),
38+
recordedDateTime: formatDateTime(recordedDate),
39+
};
40+
});
41+
}
42+
43+
class CSVAdverseEventExtractor extends Extractor {
44+
constructor({ filePath }) {
45+
super();
46+
this.CSVModule = new CSVModule(path.resolve(filePath));
47+
}
48+
49+
async getAdverseEventData(mrn) {
50+
logger.debug('Getting Adverse Event Data');
51+
return this.CSVModule.get('mrn', mrn);
52+
}
53+
54+
async get({ mrn }) {
55+
const adverseEventData = await this.getAdverseEventData(mrn);
56+
const formattedData = formatData(adverseEventData);
57+
58+
return generatemCODEResources('AdverseEvent', formattedData);
59+
}
60+
}
61+
62+
module.exports = {
63+
CSVAdverseEventExtractor,
64+
};

src/extractors/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const { BaseFHIRExtractor } = require('./BaseFHIRExtractor');
2+
const { CSVAdverseEventExtractor } = require('./CSVAdverseEventExtractor')
23
const { CSVCancerDiseaseStatusExtractor } = require('./CSVCancerDiseaseStatusExtractor');
34
const { CSVCancerRelatedMedicationExtractor } = require('./CSVCancerRelatedMedicationExtractor');
45
const { CSVClinicalTrialInformationExtractor } = require('./CSVClinicalTrialInformationExtractor');
@@ -24,6 +25,7 @@ const { MCODESurgicalProcedureExtractor } = require('./MCODESurgicalProcedureExt
2425

2526
module.exports = {
2627
BaseFHIRExtractor,
28+
CSVAdverseEventExtractor,
2729
CSVCancerDiseaseStatusExtractor,
2830
CSVCancerRelatedMedicationExtractor,
2931
CSVClinicalTrialInformationExtractor,

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const {
1010
} = require('./cli');
1111
const {
1212
BaseFHIRExtractor,
13+
CSVAdverseEventExtractor,
1314
CSVCancerDiseaseStatusExtractor,
1415
CSVCancerRelatedMedicationExtractor,
1516
CSVClinicalTrialInformationExtractor,
@@ -74,6 +75,7 @@ module.exports = {
7475
BaseClient,
7576
BaseFHIRExtractor,
7677
BaseFHIRModule,
78+
CSVAdverseEventExtractor,
7779
CSVCancerDiseaseStatusExtractor,
7880
CSVCancerRelatedMedicationExtractor,
7981
CSVClinicalTrialInformationExtractor,

src/templates/AdverseEventTemplate.js

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
const { coding, reference } = require('./snippets');
2+
const { ifAllArgsObj, ifSomeArgsObj } = require('../helpers/templateUtils');
3+
4+
function eventTemplate({ eventCode, eventSystem, eventDisplay }) {
5+
let codeSystem = eventSystem;
6+
if (!codeSystem) {
7+
codeSystem = 'http://snomed.info/sct';
8+
}
9+
return {
10+
event: {
11+
coding: [
12+
coding({
13+
code: eventCode,
14+
system: codeSystem,
15+
display: eventDisplay,
16+
}),
17+
],
18+
},
19+
};
20+
}
21+
22+
function suspectedCauseTemplate({ suspectedCauseId, suspectedCauseType }) {
23+
return {
24+
suspectEntity: [
25+
{
26+
instance:
27+
reference({ id: suspectedCauseId, resourceType: suspectedCauseType }),
28+
},
29+
],
30+
};
31+
}
32+
33+
34+
function seriousnessTemplate({ seriousnessCode, seriousnessCodeSystem, seriousnessDisplayText }) {
35+
let codeSystem = seriousnessCodeSystem;
36+
if (!codeSystem) {
37+
codeSystem = 'http://terminology.hl7.org/CodeSystem/adverse-event-seriousness';
38+
}
39+
return {
40+
seriousness: {
41+
coding: [
42+
coding({
43+
code: seriousnessCode,
44+
system: codeSystem,
45+
display: seriousnessDisplayText,
46+
}),
47+
],
48+
},
49+
};
50+
}
51+
52+
function categoryTemplate({ categoryCode, categoryCodeSystem, categoryDisplayText }) {
53+
let codeSystem = categoryCodeSystem;
54+
if (!codeSystem) {
55+
codeSystem = 'http://terminology.hl7.org/CodeSystem/adverse-event-category';
56+
}
57+
return {
58+
category: {
59+
coding: [
60+
coding({
61+
code: categoryCode,
62+
system: codeSystem,
63+
display: categoryDisplayText,
64+
}),
65+
],
66+
},
67+
};
68+
}
69+
70+
function severityTemplate({ severityCode }) {
71+
return {
72+
severity: {
73+
coding: [
74+
coding({
75+
code: severityCode,
76+
}),
77+
],
78+
},
79+
};
80+
}
81+
82+
function actualityTemplate({ actuality }) {
83+
let actualityCode = actuality;
84+
if (!actualityCode) {
85+
actualityCode = 'https://www.hl7.org/fhir/valueset-adverse-event-actuality.html';
86+
}
87+
return {
88+
actuality: {
89+
coding: [
90+
coding({
91+
code: actualityCode,
92+
}),
93+
],
94+
},
95+
};
96+
}
97+
98+
function adverseEventTemplate({
99+
id, subjectId, code, system, display, suspectedCauseId, suspectedCauseType, seriousnessCode, seriousnessCodeSystem, seriousnessDisplayText, categoryCode, categoryCodeSystem, categoryDisplayText,
100+
severity, actuality, studyId, effectiveDateTime, recordedDateTime,
101+
}) {
102+
if (!(subjectId && code && effectiveDateTime)) {
103+
throw Error('Trying to render an AdverseEventTemplate, but a required argument is messing; ensure that subjectId, code and effectiveDateTime are all present');
104+
}
105+
106+
return {
107+
resourceType: 'AdverseEvent',
108+
id,
109+
subject: reference({ id: subjectId, resourceType: 'Patient' }),
110+
...ifSomeArgsObj(eventTemplate)({ code, system, display }),
111+
...ifAllArgsObj(suspectedCauseTemplate)({ id: suspectedCauseId, resourceType: suspectedCauseType }),
112+
...ifSomeArgsObj(seriousnessTemplate)({ seriousnessCode, seriousnessCodeSystem, seriousnessDisplayText }),
113+
...ifSomeArgsObj(categoryTemplate)({ categoryCode, categoryCodeSystem, categoryDisplayText }),
114+
...ifAllArgsObj(severityTemplate)({ severity }),
115+
...actualityTemplate(actuality),
116+
study: reference({ id: studyId, resourceType: 'ResearchStudy' }),
117+
date: effectiveDateTime,
118+
recordedDate: recordedDateTime,
119+
};
120+
}
121+
122+
module.exports = {
123+
adverseEventTemplate,
124+
};

src/templates/ResourceGenerator.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const _ = require('lodash');
22
const shajs = require('sha.js');
33
const logger = require('../helpers/logger');
44

5+
const { adverseEventTemplate } = require('./AdverseEventTemplate');
56
const { cancerDiseaseStatusTemplate } = require('./CancerDiseaseStatusTemplate');
67
const { cancerRelatedMedicationTemplate } = require('./CancerRelatedMedicationTemplate');
78
const { carePlanWithReviewTemplate } = require('./CarePlanWithReviewTemplate');
@@ -15,6 +16,7 @@ const { stagingTemplate } = require('./StagingTemplate');
1516
const { tnmCategoryTemplate } = require('./TNMCategoryTemplate');
1617

1718
const fhirTemplateLookup = {
19+
AdverseEvent: adverseEventTemplate,
1820
CancerDiseaseStatus: cancerDiseaseStatusTemplate,
1921
CancerRelatedMedication: cancerRelatedMedicationTemplate,
2022
CarePlanWithReview: carePlanWithReviewTemplate,

0 commit comments

Comments
 (0)