Skip to content

Commit b99e812

Browse files
committed
Add species and admitting parsing
1 parent b6da3ed commit b99e812

3 files changed

Lines changed: 70 additions & 47 deletions

File tree

src/components/Patient.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import type * as dmv from 'dicom-microscopy-viewer'
33
import React from 'react'
44
import {
5+
formatAdmittingDiagnoses,
56
formatPatientSpeciesCodeSequence,
67
parseDate,
78
parseName,
@@ -20,10 +21,11 @@ interface PatientProps {
2021
*/
2122
class Patient extends React.Component<PatientProps, Record<string, never>> {
2223
render(): React.ReactNode {
24+
const meta = this.props.metadata as unknown as Record<string, unknown>
2325
const species = formatPatientSpeciesCodeSequence(
24-
(this.props.metadata as unknown as Record<string, unknown>)
25-
.PatientSpeciesCodeSequence,
26+
meta.PatientSpeciesCodeSequence,
2627
)
28+
const admittingDiagnosis = formatAdmittingDiagnoses(meta)
2729
const attributes = [
2830
{
2931
name: 'ID',
@@ -44,9 +46,11 @@ class Patient extends React.Component<PatientProps, Record<string, never>> {
4446
},
4547
{
4648
name: 'Age',
47-
value: (this.props.metadata as unknown as Record<string, unknown>)
48-
.PatientAge as string | undefined,
49+
value: meta.PatientAge as string | undefined,
4950
},
51+
...(admittingDiagnosis !== undefined
52+
? [{ name: 'Admitting diagnosis', value: admittingDiagnosis }]
53+
: []),
5054
]
5155
return <Description attributes={attributes} />
5256
}

src/components/SpecimenItem.tsx

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@ import * as dcmjs from 'dcmjs'
44
import type * as dmv from 'dicom-microscopy-viewer'
55
import React from 'react'
66
import { SpecimenPreparationStepItems } from '../data/specimens'
7-
import {
8-
codedConceptDisplayText,
9-
dedupeStringsPreserveOrder,
10-
} from '../utils/values'
117
import type { Attribute } from './Description'
128
import Item from './Item'
139

@@ -17,35 +13,6 @@ interface SpecimenItemProps {
1713
showstain: boolean
1814
}
1915

20-
/** (0008,1080) LO and (0008,1084) SQ — separate DICOM attributes; combine for display. */
21-
function formatAdmittingDiagnoses(
22-
metadata: Record<string, unknown>,
23-
): string | undefined {
24-
const descRaw = metadata.AdmittingDiagnosesDescription
25-
const desc = typeof descRaw === 'string' ? descRaw.trim() : ''
26-
27-
const seq = metadata.AdmittingDiagnosesCodeSequence
28-
const codeParts: string[] = []
29-
if (Array.isArray(seq)) {
30-
for (const item of seq) {
31-
const part = codedConceptDisplayText(item)
32-
if (part !== '') codeParts.push(part)
33-
}
34-
}
35-
const uniqueCodes = dedupeStringsPreserveOrder(codeParts)
36-
const codesJoined = uniqueCodes.join(', ')
37-
38-
if (desc !== '' && codesJoined !== '') {
39-
if (desc.toLowerCase() === codesJoined.toLowerCase()) {
40-
return desc
41-
}
42-
return `${desc}; ${codesJoined}`
43-
}
44-
if (desc !== '') return desc
45-
if (codesJoined !== '') return codesJoined
46-
return undefined
47-
}
48-
4916
/**
5017
* React component representing a DICOM Specimen Information Entity and
5118
* displays specimen-related attributes of a DICOM Slide Microscopy image.
@@ -193,16 +160,6 @@ class SpecimenItem extends React.Component<
193160
},
194161
)
195162

196-
const admittingDiagnoses = formatAdmittingDiagnoses(
197-
this.props.metadata as unknown as Record<string, unknown>,
198-
)
199-
if (admittingDiagnoses !== undefined) {
200-
attributes.push({
201-
name: 'Admitting Diagnoses',
202-
value: admittingDiagnoses,
203-
})
204-
}
205-
206163
const uid = specimenDescription.SpecimenUID
207164
const identifier = specimenDescription.SpecimenIdentifier
208165

src/utils/values.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,67 @@ function dedupeStringsPreserveOrder(strings: string[]): string[] {
8686
return out
8787
}
8888

89+
/**
90+
* (0008,1080) LO + (0008,1084) SQ (standard keywords use plural "Diagnoses").
91+
* Also accepts singular / legacy keys (e.g. dcmjs) for interoperability.
92+
*/
93+
function formatAdmittingDiagnoses(
94+
metadata: Record<string, unknown>,
95+
): string | undefined {
96+
let desc = ''
97+
for (const key of [
98+
'AdmittingDiagnosesDescription',
99+
'AdmittingDiagnosisDescription',
100+
] as const) {
101+
const v = metadata[key]
102+
if (typeof v === 'string' && v.trim() !== '') {
103+
desc = v.trim()
104+
break
105+
}
106+
}
107+
108+
const codeSeqKeys = [
109+
'AdmittingDiagnosesCodeSequence',
110+
'AdmittingDiagnosisCodeSequence',
111+
'AdmittingDiagnosisCodeSeq',
112+
] as const
113+
let seq: unknown[] = []
114+
for (const key of codeSeqKeys) {
115+
const v = metadata[key]
116+
if (Array.isArray(v) && v.length > 0) {
117+
seq = v
118+
break
119+
}
120+
}
121+
if (seq.length === 0) {
122+
for (const key of codeSeqKeys) {
123+
const v = metadata[key]
124+
if (Array.isArray(v)) {
125+
seq = v
126+
break
127+
}
128+
}
129+
}
130+
131+
const codeParts: string[] = []
132+
for (const item of seq) {
133+
const part = codedConceptDisplayText(item)
134+
if (part !== '') codeParts.push(part)
135+
}
136+
const uniqueCodes = dedupeStringsPreserveOrder(codeParts)
137+
const codesJoined = uniqueCodes.join(', ')
138+
139+
if (desc !== '' && codesJoined !== '') {
140+
if (desc.toLowerCase() === codesJoined.toLowerCase()) {
141+
return desc
142+
}
143+
return `${desc}; ${codesJoined}`
144+
}
145+
if (desc !== '') return desc
146+
if (codesJoined !== '') return codesJoined
147+
return undefined
148+
}
149+
89150
/** (00102202) PatientSpeciesCodeSequence — meanings only; undefined if absent or empty. */
90151
function formatPatientSpeciesCodeSequence(
91152
sequence: unknown,
@@ -105,6 +166,7 @@ function formatPatientSpeciesCodeSequence(
105166
export {
106167
codedConceptDisplayText,
107168
dedupeStringsPreserveOrder,
169+
formatAdmittingDiagnoses,
108170
formatPatientSpeciesCodeSequence,
109171
parseDate,
110172
parseDateTime,

0 commit comments

Comments
 (0)