Skip to content

Commit

Permalink
Merge pull request #49 from mcode/convert-tnm-to-staging
Browse files Browse the repository at this point in the history
Add API to convert TNM values to a cancer stage number
  • Loading branch information
zlister authored Jun 26, 2024
2 parents f11a601 + 3f9e2e4 commit 8d0d668
Show file tree
Hide file tree
Showing 8 changed files with 1,117 additions and 2 deletions.
23 changes: 23 additions & 0 deletions TNM Staging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Converting TNM to a Staging Value

The current algorithm for determining the numeric staging algorithm is based on
the [TNM classification](https://www.ncbi.nlm.nih.gov/books/NBK553187/) and
works as follows:

1. If M is 1, staging is 4. Skip remaining steps.
2. If N is greater than 0, staging is 3. Skip remaining steps.
3. If T is greater than 2, staging is 2. Skip remaining steps.
4. If T is 1, staging is 1. Skip remaining steps.
5. If T is "is" (in situ), staging is 0. Skip remaining steps.
6. Otherwise, the value is T0 N0 M0 which is effectively "no cancer." This has no corresponding staging, so staging is `null`.

This breaks down as follows:

| T | N | M | Staging |
|--------|------------|----|---------|
| T0 | N0 | M0 | `null` |
| Tis | N0 | M0 | 0 |
| T1, T2 | N0 | M0 | 1 |
| T3, T4 | N0 | M0 | 2 |
| (any) | N1, N2, N3 | M0 | 3 |
| (any) | (any) | M1 | 4 |
150 changes: 149 additions & 1 deletion spec/fhir-util.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { FhirResource } from 'fhir/r4';
import { FHIRDate, FHIRDateAccuracy, resourceContainsProfile } from '../src/fhir-util';
import {
FHIRDate,
FHIRDateAccuracy,
codeableConceptContains,
codeableConceptContainsCode,
resourceContainsProfile
} from '../src/fhir-util';

describe('#resourceContainsProfile', () => {
it('handles resources with no meta', () => {
Expand Down Expand Up @@ -117,3 +123,145 @@ describe('FHIRDate', () => {
});
});
});

describe('codeableConceptContains', () => {
// Simple test set
const CODE_SET = { '1_2': ['1', '2'], '3_4': ['3', '4'] };
it('handles a codeable concept with no codes', () => {
expect(codeableConceptContains({}, CODE_SET)).toBeFalse();
});
it('returns false for codes in the other system', () => {
expect(
codeableConceptContains(
{
coding: [
{
system: '1_2',
code: '3'
},
{
system: '3_4',
code: '1'
}
]
},
CODE_SET
)
).toBeFalse();
});
it('handles partial codes', () => {
expect(
codeableConceptContains(
{
coding: [
{
code: '1'
},
{
system: '3_4'
}
]
},
CODE_SET
)
).toBeFalse();
});
it('returns true for codes that exist', () => {
expect(
codeableConceptContains(
{
coding: [
{
system: 'ignore me',
code: 'code'
},
{
system: '3_4',
code: '4'
}
]
},
CODE_SET
)
).toBeTrue();
});
});

describe('codeableConceptContainsCode', () => {
// Simple test set
const SYSTEM = '1_2';
const CODE_SET = ['1', '2'];
it('handles a codeable concept with no codes', () => {
expect(codeableConceptContainsCode({}, SYSTEM, CODE_SET)).toBeFalse();
});
it("returns false for codes that don't exist", () => {
expect(
codeableConceptContainsCode(
{
coding: [
{
system: '1_2',
code: '3'
}
]
},
SYSTEM,
CODE_SET
)
).toBeFalse();
});
it('returns false for codes in another system', () => {
expect(
codeableConceptContainsCode(
{
coding: [
{
system: '3_4',
code: '1'
}
]
},
SYSTEM,
CODE_SET
)
).toBeFalse();
});
it('handles partial codes', () => {
expect(
codeableConceptContainsCode(
{
coding: [
{
code: '1'
},
{
system: '3_4'
}
]
},
SYSTEM,
CODE_SET
)
).toBeFalse();
});
it('returns true for codes that exist', () => {
expect(
codeableConceptContainsCode(
{
coding: [
{
system: 'ignore me',
code: 'code'
},
{
system: '1_2',
code: '2'
}
]
},
SYSTEM,
CODE_SET
)
).toBeTrue();
});
});
Loading

0 comments on commit 8d0d668

Please sign in to comment.