Skip to content

Commit cca8410

Browse files
authored
Merge pull request #63 from mcode/staging-method
Staging method in the form of a `stagingSystem` property
2 parents 11625a8 + 85c469a commit cca8410

16 files changed

+269
-42
lines changed

docs/CSV Templates 20200806.xlsx

96 Bytes
Binary file not shown.

docs/staging.csv

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
mrn,conditionId,stageGroup,t,n,m,type,effectiveDate
2-
mrn-1,example-condition-id,3C,cT3,cN3,cM0,Clinical,2020-01-01
1+
mrn,conditionId,stageGroup,t,n,m,type,stagingSystem,effectiveDate
2+
mrn-1,example-condition-id,3C,cT3,cN3,cM0,Clinical,443830009,2020-01-01

src/extractors/CSVStagingExtractor.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ function formatTNMCategoryData(stagingData) {
1010
logger.debug('Reformatting TNM Category data into template format');
1111
const formattedData = [];
1212
const {
13-
mrn, conditionId, t, n, m, type, effectiveDate,
13+
mrn, conditionId, t, n, m, type, stagingSystem, effectiveDate,
1414
} = stagingData;
1515

1616
if (!mrn || !conditionId || !effectiveDate) {
@@ -22,6 +22,7 @@ function formatTNMCategoryData(stagingData) {
2222
conditionId,
2323
effectiveDateTime: formatDateTime(effectiveDate),
2424
stageType: type,
25+
stagingSystem,
2526
subjectId: mrn,
2627
};
2728

@@ -34,14 +35,15 @@ function formatTNMCategoryData(stagingData) {
3435

3536
function formatStagingData(stagingData, categoryIds) {
3637
const {
37-
mrn, conditionId, type, stageGroup, effectiveDate,
38+
mrn, conditionId, type, stageGroup, stagingSystem, effectiveDate,
3839
} = stagingData;
3940

4041
return {
4142
subjectId: mrn,
4243
conditionId,
4344
type,
4445
stageGroup,
46+
stagingSystem,
4547
effectiveDateTime: formatDateTime(effectiveDate),
4648
categoryIds,
4749
};

src/helpers/cancerStagingUtils.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const cancerStagingSystemVS = require('../valueSets/ValueSet-mcode-cancer-staging-system-vs.json');
2+
3+
function checkCodeInVS(code, valueSet) {
4+
return valueSet.compose.include[0].concept.map((c) => c.code).includes(code);
5+
}
6+
7+
function isCancerStagingSystem(code) {
8+
return checkCodeInVS(code, cancerStagingSystemVS);
9+
}
10+
11+
module.exports = {
12+
isCancerStagingSystem,
13+
};

src/templates/StagingTemplate.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { coding, reference, valueX } = require('./snippets');
1+
const { coding, reference, stagingMethodTemplate, valueX } = require('./snippets');
22

33
// Returns staging specific data based whether it is clinical or pathologic
44
function getTypeSpecificData(type) {
@@ -30,13 +30,14 @@ function hasMemberTemplate(categoryIds) {
3030
}
3131

3232
function stagingTemplate({
33+
categoryIds,
34+
conditionId,
35+
effectiveDateTime,
3336
id,
37+
stageGroup,
38+
stagingSystem,
3439
subjectId,
35-
conditionId,
3640
type,
37-
stageGroup,
38-
effectiveDateTime,
39-
categoryIds,
4041
}) {
4142
if (!(id && subjectId && conditionId && effectiveDateTime && stageGroup && type)) {
4243
throw Error('Trying to render a StagingTemplate, but a required argument is missing;'
@@ -72,6 +73,7 @@ function stagingTemplate({
7273
}),
7374
],
7475
},
76+
...stagingMethodTemplate({ code: stagingSystem }),
7577
subject: reference({ id: subjectId }),
7678
effectiveDateTime,
7779
...valueX({ code: stageGroup, system: 'http://cancerstaging.org' }, 'valueCodeableConcept'),

src/templates/TNMCategoryTemplate.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { coding, reference, valueX } = require('./snippets');
1+
const { coding, reference, stagingMethodTemplate, valueX } = require('./snippets');
22

33
// Returns category specific data based on stage and category type
44
function getCategorySpecificData(stageType, categoryType) {
@@ -54,7 +54,14 @@ function getCategorySpecificData(stageType, categoryType) {
5454
}
5555

5656
function tnmCategoryTemplate({
57-
id, subjectId, conditionId, valueCode, effectiveDateTime, categoryType, stageType,
57+
categoryType,
58+
conditionId,
59+
effectiveDateTime,
60+
id,
61+
stageType,
62+
stagingSystem,
63+
subjectId,
64+
valueCode,
5865
}) {
5966
if (!(id && subjectId && conditionId && valueCode && effectiveDateTime && categoryType && stageType)) {
6067
throw Error('Trying to render a TNMCategoryTemplate, but a required argument is missing;'
@@ -91,6 +98,7 @@ function tnmCategoryTemplate({
9198
],
9299
},
93100
subject: reference({ id: subjectId }),
101+
...stagingMethodTemplate({ code: stagingSystem }),
94102
effectiveDateTime,
95103
...valueX({ code: valueCode, system: 'http://cancerstaging.org' }, 'valueCodeableConcept'),
96104
focus: [reference({ id: conditionId })],
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const _ = require('lodash');
2+
const logger = require('../../helpers/logger');
3+
const { ifSomeArgsObj } = require('../../helpers/templateUtils');
4+
const { isCancerStagingSystem } = require('../../helpers/cancerStagingUtils');
5+
const { coding } = require('./coding');
6+
7+
function methodTemplate({ code, system }) {
8+
return ifSomeArgsObj(
9+
({ code: code_, system: system_ }) => ({
10+
method: {
11+
coding: [
12+
coding({
13+
...(code_ && { code: code_ }),
14+
...(system_ && { system: system_ }),
15+
}),
16+
],
17+
},
18+
}),
19+
)({ code, system });
20+
}
21+
22+
function stagingMethodTemplate({ code }) {
23+
if (isCancerStagingSystem(code)) {
24+
// NOTE: our general value set lookup should probably return the associate system, since it's available at the VS level
25+
return methodTemplate({ code, system: 'http://snomed.info/sct' });
26+
} if (code === 'C146985') {
27+
// TODO: fix this HARDCODED special case as delineated by this VS's description http://hl7.org/fhir/us/mcode/ValueSet-mcode-cancer-staging-system-vs.html
28+
// System based on http://hl7.org/fhir/us/mcode/Observation-mCODETNMClinicalPrimaryTumorCategoryExample01.json.html
29+
return methodTemplate({ code, system: 'http://ncimeta.nci.nih.gov' });
30+
}
31+
if (!_.isNull(code)) {
32+
logger.debug(`stagingMethodTemplate received a code ${code} that is not recognized; code will be added without a codeSystem if possible`);
33+
}
34+
return methodTemplate({ code });
35+
}
36+
37+
module.exports = {
38+
stagingMethodTemplate,
39+
};

src/templates/snippets/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const { extensionArr, dataAbsentReasonExtension } = require('./extension');
66
const { effectiveX } = require('./effectiveX');
77
const { identifier, identifierArr } = require('./identifier');
88
const { bodySiteTemplate } = require('./bodySiteTemplate');
9+
const { stagingMethodTemplate } = require('./cancerStaging');
910

1011
module.exports = {
1112
bodySiteTemplate,
@@ -18,5 +19,6 @@ module.exports = {
1819
meta,
1920
narrative,
2021
reference,
22+
stagingMethodTemplate,
2123
valueX,
2224
};
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"resourceType": "ValueSet",
3+
"id": "mcode-cancer-staging-system-vs",
4+
"text": {
5+
"status": "generated",
6+
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><h2>Cancer Staging System Value Set</h2><div><p>System used for staging. If the staging system is AJCC Version 8, use the NCI thesaurus code C146985 (AJCC Cancer Staging Manual 8th Edition) in its place. This is because SNOMED does not have an equivalent concept for AJCC Version 8 at this time.</p>\n</div><ul><li>Include these codes as defined in <a href=\"http://www.snomed.org/\"><code>http://snomed.info/sct</code></a><table class=\"none\"><tr><td style=\"white-space:nowrap\"><b>Code</b></td><td><b>Display</b></td></tr><tr><td><a href=\"http://browser.ihtsdotools.org/?perspective=full&amp;conceptId1=444256004\">444256004</a></td><td>American Joint Commission on Cancer, Cancer Staging Manual, 6th edition neoplasm staging system (tumor staging)</td><td/></tr><tr><td><a href=\"http://browser.ihtsdotools.org/?perspective=full&amp;conceptId1=443830009\">443830009</a></td><td>American Joint Commission on Cancer, Cancer Staging Manual, 7th edition neoplasm staging system (tumor staging)</td><td/></tr><tr><td><a href=\"http://browser.ihtsdotools.org/?perspective=full&amp;conceptId1=258235000\">258235000</a></td><td>International Union Against Cancer (tumor staging)</td><td/></tr></table></li></ul></div>"
7+
},
8+
"url": "http://hl7.org/fhir/us/mcode/ValueSet/mcode-cancer-staging-system-vs",
9+
"version": "1.0.0",
10+
"name": "CancerStagingSystemVS",
11+
"title": "Cancer Staging System Value Set",
12+
"status": "active",
13+
"date": "2020-03-18T16:05:09+00:00",
14+
"publisher": "HL7 International Clinical Interoperability Council",
15+
"contact": [
16+
{
17+
"name": "HL7 International Clinical Interoperability Council",
18+
"telecom": [
19+
{
20+
"system": "url",
21+
"value": "http://www.hl7.org/Special/committees/cic"
22+
},
23+
{
24+
"system": "email",
25+
"value": "ciclist@lists.HL7.org"
26+
}
27+
]
28+
}
29+
],
30+
"description": "System used for staging. If the staging system is AJCC Version 8, use the NCI thesaurus code C146985 (AJCC Cancer Staging Manual 8th Edition) in its place. This is because SNOMED does not have an equivalent concept for AJCC Version 8 at this time.",
31+
"compose": {
32+
"include": [
33+
{
34+
"system": "http://snomed.info/sct",
35+
"concept": [
36+
{
37+
"code": "444256004",
38+
"display": "American Joint Commission on Cancer, Cancer Staging Manual, 6th edition neoplasm staging system (tumor staging)"
39+
},
40+
{
41+
"code": "443830009",
42+
"display": "American Joint Commission on Cancer, Cancer Staging Manual, 7th edition neoplasm staging system (tumor staging)"
43+
},
44+
{
45+
"code": "258235000",
46+
"display": "International Union Against Cancer (tumor staging)"
47+
}
48+
]
49+
}
50+
]
51+
}
52+
}

test/extractors/CSVStagingExtractor.test.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,22 @@ describe('CSVStagingExtractor', () => {
2828
// Test that valid data works fine
2929
expect(formatTNMCategoryData(localData)).toEqual(expect.anything());
3030

31-
// Test all optional properties can be removed without throwing errors
32-
delete localData.t;
33-
delete localData.m;
34-
delete localData.n;
35-
delete localData.type;
36-
delete localData.stageGroup;
31+
// Test all optional properties can be empty without issue
32+
localData.t = '';
33+
localData.m = '';
34+
localData.n = '';
35+
localData.type = '';
36+
localData.stagingSystem = '';
37+
localData.stageGroup = '';
3738

3839
// Only including required properties is valid
3940
expect(formatTNMCategoryData(localData)).toEqual(expect.anything());
4041

4142
// Removing each required property should throw an error
42-
Object.keys(localData).forEach((key) => {
43+
const requiredKeys = ['mrn', 'conditionId', 'effectiveDate'];
44+
requiredKeys.forEach((key) => {
4345
const clonedData = _.cloneDeep(localData);
44-
delete clonedData[key];
46+
clonedData[key] = '';
4547
expect(() => formatTNMCategoryData(clonedData)).toThrow(new Error(expectedErrorString));
4648
});
4749
});

0 commit comments

Comments
 (0)