@cornerstonejs/metadata 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/esm/enums/CalibrationTypes.d.ts +12 -0
- package/dist/esm/enums/CalibrationTypes.js +13 -0
- package/dist/esm/enums/MetadataModules.d.ts +54 -0
- package/dist/esm/enums/MetadataModules.js +57 -0
- package/dist/esm/enums/index.d.ts +4 -0
- package/dist/esm/enums/index.js +4 -0
- package/dist/esm/index.d.ts +10 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/metaData.d.ts +33 -0
- package/dist/esm/metaData.js +181 -0
- package/dist/esm/registerDefaultProviders.d.ts +1 -0
- package/dist/esm/registerDefaultProviders.js +38 -0
- package/dist/esm/types/DicomStreamTypes.d.ts +13 -0
- package/dist/esm/types/DicomStreamTypes.js +0 -0
- package/dist/esm/types/IImageCalibration.d.ts +11 -0
- package/dist/esm/types/IImageCalibration.js +0 -0
- package/dist/esm/types/MetadataModuleTypes.d.ts +100 -0
- package/dist/esm/types/MetadataModuleTypes.js +0 -0
- package/dist/esm/types/index.d.ts +3 -0
- package/dist/esm/types/index.js +0 -0
- package/dist/esm/utilities/Tags.d.ts +25 -0
- package/dist/esm/utilities/Tags.js +112 -0
- package/dist/esm/utilities/bulkDataFromArray.d.ts +1 -0
- package/dist/esm/utilities/bulkDataFromArray.js +38 -0
- package/dist/esm/utilities/calibratedPixelSpacingMetadataProvider.d.ts +7 -0
- package/dist/esm/utilities/calibratedPixelSpacingMetadataProvider.js +21 -0
- package/dist/esm/utilities/dicomStream/MetaDataIterator.d.ts +11 -0
- package/dist/esm/utilities/dicomStream/MetaDataIterator.js +58 -0
- package/dist/esm/utilities/dicomStream/NaturalTagListener.d.ts +22 -0
- package/dist/esm/utilities/dicomStream/NaturalTagListener.js +106 -0
- package/dist/esm/utilities/dicomStream/index.d.ts +3 -0
- package/dist/esm/utilities/dicomStream/index.js +2 -0
- package/dist/esm/utilities/getNaturalizedField.d.ts +3 -0
- package/dist/esm/utilities/getNaturalizedField.js +34 -0
- package/dist/esm/utilities/getPixelSpacingInformation.d.ts +13 -0
- package/dist/esm/utilities/getPixelSpacingInformation.js +93 -0
- package/dist/esm/utilities/imageIdToURI.d.ts +1 -0
- package/dist/esm/utilities/imageIdToURI.js +15 -0
- package/dist/esm/utilities/index.d.ts +15 -0
- package/dist/esm/utilities/index.js +15 -0
- package/dist/esm/utilities/isEqual.d.ts +2 -0
- package/dist/esm/utilities/isEqual.js +2 -0
- package/dist/esm/utilities/isVideoTransferSyntax.d.ts +2 -0
- package/dist/esm/utilities/isVideoTransferSyntax.js +25 -0
- package/dist/esm/utilities/logging.d.ts +3 -0
- package/dist/esm/utilities/logging.js +2 -0
- package/dist/esm/utilities/metadataProvider/addDicomPart10Instance.d.ts +2 -0
- package/dist/esm/utilities/metadataProvider/addDicomPart10Instance.js +12 -0
- package/dist/esm/utilities/metadataProvider/cacheData.d.ts +39 -0
- package/dist/esm/utilities/metadataProvider/cacheData.js +235 -0
- package/dist/esm/utilities/metadataProvider/calibrationModule.d.ts +2 -0
- package/dist/esm/utilities/metadataProvider/calibrationModule.js +25 -0
- package/dist/esm/utilities/metadataProvider/combineFrameInstance.d.ts +5 -0
- package/dist/esm/utilities/metadataProvider/combineFrameInstance.js +158 -0
- package/dist/esm/utilities/metadataProvider/compressedFrameData.d.ts +1 -0
- package/dist/esm/utilities/metadataProvider/compressedFrameData.js +133 -0
- package/dist/esm/utilities/metadataProvider/dataLookup.d.ts +7 -0
- package/dist/esm/utilities/metadataProvider/dataLookup.js +18 -0
- package/dist/esm/utilities/metadataProvider/dicomSplit.d.ts +1 -0
- package/dist/esm/utilities/metadataProvider/dicomSplit.js +5 -0
- package/dist/esm/utilities/metadataProvider/ecgFromInstance.d.ts +18 -0
- package/dist/esm/utilities/metadataProvider/ecgFromInstance.js +228 -0
- package/dist/esm/utilities/metadataProvider/ecgModule.d.ts +1 -0
- package/dist/esm/utilities/metadataProvider/ecgModule.js +0 -0
- package/dist/esm/utilities/metadataProvider/imageIdsProviders.d.ts +11 -0
- package/dist/esm/utilities/metadataProvider/imageIdsProviders.js +117 -0
- package/dist/esm/utilities/metadataProvider/imagePlaneCalibrated.d.ts +4 -0
- package/dist/esm/utilities/metadataProvider/imagePlaneCalibrated.js +89 -0
- package/dist/esm/utilities/metadataProvider/index.d.ts +18 -0
- package/dist/esm/utilities/metadataProvider/index.js +17 -0
- package/dist/esm/utilities/metadataProvider/instanceFromListener.d.ts +2 -0
- package/dist/esm/utilities/metadataProvider/instanceFromListener.js +9 -0
- package/dist/esm/utilities/metadataProvider/makeArrayLike.d.ts +1 -0
- package/dist/esm/utilities/metadataProvider/makeArrayLike.js +25 -0
- package/dist/esm/utilities/metadataProvider/naturalizedHandlers.d.ts +5 -0
- package/dist/esm/utilities/metadataProvider/naturalizedHandlers.js +67 -0
- package/dist/esm/utilities/metadataProvider/pixelDataUpdate.d.ts +2 -0
- package/dist/esm/utilities/metadataProvider/pixelDataUpdate.js +133 -0
- package/dist/esm/utilities/metadataProvider/scalingFromInstance.d.ts +1 -0
- package/dist/esm/utilities/metadataProvider/scalingFromInstance.js +148 -0
- package/dist/esm/utilities/metadataProvider/tagModules.d.ts +7 -0
- package/dist/esm/utilities/metadataProvider/tagModules.js +62 -0
- package/dist/esm/utilities/metadataProvider/transferSyntaxProvider.d.ts +2 -0
- package/dist/esm/utilities/metadataProvider/transferSyntaxProvider.js +20 -0
- package/dist/esm/utilities/metadataProvider/uriModule.d.ts +19 -0
- package/dist/esm/utilities/metadataProvider/uriModule.js +26 -0
- package/dist/esm/utilities/modules/cine.d.ts +2 -0
- package/dist/esm/utilities/modules/cine.js +4 -0
- package/dist/esm/utilities/modules/clinicalTrial.d.ts +2 -0
- package/dist/esm/utilities/modules/clinicalTrial.js +6 -0
- package/dist/esm/utilities/modules/ecg.d.ts +2 -0
- package/dist/esm/utilities/modules/ecg.js +11 -0
- package/dist/esm/utilities/modules/generalImage.d.ts +2 -0
- package/dist/esm/utilities/modules/generalImage.js +14 -0
- package/dist/esm/utilities/modules/generalSeries.d.ts +2 -0
- package/dist/esm/utilities/modules/generalSeries.js +11 -0
- package/dist/esm/utilities/modules/generalStudy.d.ts +2 -0
- package/dist/esm/utilities/modules/generalStudy.js +7 -0
- package/dist/esm/utilities/modules/imagePixel.d.ts +2 -0
- package/dist/esm/utilities/modules/imagePixel.js +31 -0
- package/dist/esm/utilities/modules/imagePlane.d.ts +2 -0
- package/dist/esm/utilities/modules/imagePlane.js +8 -0
- package/dist/esm/utilities/modules/index.d.ts +5 -0
- package/dist/esm/utilities/modules/index.js +48 -0
- package/dist/esm/utilities/modules/modalityLut.d.ts +2 -0
- package/dist/esm/utilities/modules/modalityLut.js +5 -0
- package/dist/esm/utilities/modules/patient.d.ts +2 -0
- package/dist/esm/utilities/modules/patient.js +6 -0
- package/dist/esm/utilities/modules/patientStudy.d.ts +2 -0
- package/dist/esm/utilities/modules/patientStudy.js +6 -0
- package/dist/esm/utilities/modules/ptImage.d.ts +2 -0
- package/dist/esm/utilities/modules/ptImage.js +4 -0
- package/dist/esm/utilities/modules/ptIsotope.d.ts +2 -0
- package/dist/esm/utilities/modules/ptIsotope.js +1 -0
- package/dist/esm/utilities/modules/ptSeries.d.ts +2 -0
- package/dist/esm/utilities/modules/ptSeries.js +5 -0
- package/dist/esm/utilities/modules/radiopharmaceuticalInfo.d.ts +2 -0
- package/dist/esm/utilities/modules/radiopharmaceuticalInfo.js +6 -0
- package/dist/esm/utilities/modules/sopCommon.d.ts +2 -0
- package/dist/esm/utilities/modules/sopCommon.js +1 -0
- package/dist/esm/utilities/modules/transferSyntax.d.ts +2 -0
- package/dist/esm/utilities/modules/transferSyntax.js +4 -0
- package/dist/esm/utilities/modules/ultrasoundEnhancedRegion.d.ts +2 -0
- package/dist/esm/utilities/modules/ultrasoundEnhancedRegion.js +1 -0
- package/dist/esm/utilities/modules/unassigned.d.ts +2 -0
- package/dist/esm/utilities/modules/unassigned.js +15 -0
- package/dist/esm/utilities/modules/usRegionChild.d.ts +2 -0
- package/dist/esm/utilities/modules/usRegionChild.js +18 -0
- package/dist/esm/utilities/modules/voiLut.d.ts +2 -0
- package/dist/esm/utilities/modules/voiLut.js +6 -0
- package/dist/esm/utilities/splitImageIdsBy4DTags.d.ts +12 -0
- package/dist/esm/utilities/splitImageIdsBy4DTags.js +314 -0
- package/dist/esm/utilities/toNumber.d.ts +2 -0
- package/dist/esm/utilities/toNumber.js +2 -0
- package/dist/esm/version.d.ts +1 -0
- package/dist/esm/version.js +1 -0
- package/package.json +99 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { MetadataModules } from '../../enums';
|
|
2
|
+
import { addTypedProvider } from '../../metaData';
|
|
3
|
+
import { getSingleBufferFromArray } from '../bulkDataFromArray';
|
|
4
|
+
function normalizePaletteLUT(raw) {
|
|
5
|
+
if (raw instanceof ArrayBuffer) {
|
|
6
|
+
const len = raw.byteLength;
|
|
7
|
+
return {
|
|
8
|
+
view: len <= 256 ? new Uint8Array(raw) : new Uint16Array(raw),
|
|
9
|
+
byteLength: len,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
if (ArrayBuffer.isView(raw)) {
|
|
13
|
+
const v = raw;
|
|
14
|
+
return { view: v, byteLength: v.byteLength };
|
|
15
|
+
}
|
|
16
|
+
if (Array.isArray(raw)) {
|
|
17
|
+
const view = getSingleBufferFromArray(raw);
|
|
18
|
+
if (view) {
|
|
19
|
+
return {
|
|
20
|
+
view: view,
|
|
21
|
+
byteLength: view.byteLength,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const inline = raw != null &&
|
|
26
|
+
typeof raw === 'object' &&
|
|
27
|
+
'InlineBinary' in raw &&
|
|
28
|
+
typeof raw.InlineBinary === 'string';
|
|
29
|
+
if (inline) {
|
|
30
|
+
const b64 = raw.InlineBinary;
|
|
31
|
+
const binary = atob(b64);
|
|
32
|
+
const bytes = new Uint8Array(binary.length);
|
|
33
|
+
for (let i = 0; i < binary.length; i++) {
|
|
34
|
+
bytes[i] = binary.charCodeAt(i);
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
view: bytes,
|
|
38
|
+
byteLength: bytes.byteLength,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const desc = describeValue(raw);
|
|
42
|
+
throw new Error('Palette color lookup table data could not be normalized: expected ArrayBuffer, ArrayBufferView, or object with InlineBinary string. ' +
|
|
43
|
+
desc);
|
|
44
|
+
}
|
|
45
|
+
function normalizePaletteLUTToFinal(raw, descriptor, color) {
|
|
46
|
+
descriptor[0] ||= 65536;
|
|
47
|
+
const tableLen = descriptor[0];
|
|
48
|
+
const bits = descriptor[2] ?? 16;
|
|
49
|
+
const { view, byteLength } = normalizePaletteLUT(raw);
|
|
50
|
+
const expectedByteLengths = [tableLen, tableLen * 2];
|
|
51
|
+
if (!expectedByteLengths.includes(byteLength)) {
|
|
52
|
+
const actualEntries = byteLength === tableLen ? view.length : Math.floor(byteLength / 2);
|
|
53
|
+
throw new Error(`Palette color lookup table length mismatch (${color}): descriptor has ${tableLen} entries (expected byteLength ${tableLen} or ${tableLen * 2}), but got ${byteLength} bytes (${actualEntries} effective entries). This may indicate duplicated or concatenated buffer data from the natural filter.`);
|
|
54
|
+
}
|
|
55
|
+
const use8 = tableLen === byteLength;
|
|
56
|
+
if (use8) {
|
|
57
|
+
return view instanceof Uint8Array ? view : new Uint8Array(view);
|
|
58
|
+
}
|
|
59
|
+
return view instanceof Uint16Array
|
|
60
|
+
? view
|
|
61
|
+
: new Uint16Array(view.buffer, view.byteOffset, view.byteLength / 2);
|
|
62
|
+
}
|
|
63
|
+
function describeValue(raw) {
|
|
64
|
+
if (raw === null)
|
|
65
|
+
return 'Got null.';
|
|
66
|
+
if (raw === undefined)
|
|
67
|
+
return 'Got undefined.';
|
|
68
|
+
if (typeof raw !== 'object')
|
|
69
|
+
return `Got primitive: ${typeof raw}.`;
|
|
70
|
+
const obj = raw;
|
|
71
|
+
const constructorName = obj.constructor != null && typeof obj.constructor === 'function'
|
|
72
|
+
? obj.constructor.name
|
|
73
|
+
: 'unknown';
|
|
74
|
+
const keys = Object.keys(obj);
|
|
75
|
+
const preview = {};
|
|
76
|
+
for (const k of keys) {
|
|
77
|
+
const v = obj[k];
|
|
78
|
+
if (v === null)
|
|
79
|
+
preview[k] = 'null';
|
|
80
|
+
else if (v === undefined)
|
|
81
|
+
preview[k] = 'undefined';
|
|
82
|
+
else if (typeof v === 'string')
|
|
83
|
+
preview[k] =
|
|
84
|
+
v.length > 80
|
|
85
|
+
? `"${v.slice(0, 80)}..." (len=${v.length})`
|
|
86
|
+
: JSON.stringify(v);
|
|
87
|
+
else if (Array.isArray(v))
|
|
88
|
+
preview[k] =
|
|
89
|
+
`Array(${v.length})${v.length > 0 ? ` e.g. ${JSON.stringify(v[0])}` : ''}`;
|
|
90
|
+
else if (v instanceof ArrayBuffer)
|
|
91
|
+
preview[k] = `ArrayBuffer(${v.byteLength})`;
|
|
92
|
+
else if (ArrayBuffer.isView(v))
|
|
93
|
+
preview[k] =
|
|
94
|
+
`${v.constructor?.name ?? 'ArrayBufferView'}(${v.byteLength})`;
|
|
95
|
+
else
|
|
96
|
+
preview[k] = typeof v;
|
|
97
|
+
}
|
|
98
|
+
return `Got object: constructor=${constructorName}, keys=[${keys.join(', ')}], preview=${JSON.stringify(preview)}.`;
|
|
99
|
+
}
|
|
100
|
+
export function pixelDataUpdate(next, query, data, options) {
|
|
101
|
+
const basePixelData = next(query, data, options);
|
|
102
|
+
if (!basePixelData) {
|
|
103
|
+
return basePixelData;
|
|
104
|
+
}
|
|
105
|
+
const result = { ...basePixelData };
|
|
106
|
+
const { redPaletteColorLookupTableData, greenPaletteColorLookupTableData, bluePaletteColorLookupTableData, pixelPaddingValue, pixelPaddingRangeLimit, pixelRepresentation, } = basePixelData;
|
|
107
|
+
if (redPaletteColorLookupTableData != null &&
|
|
108
|
+
greenPaletteColorLookupTableData != null &&
|
|
109
|
+
bluePaletteColorLookupTableData != null) {
|
|
110
|
+
result.redPaletteColorLookupTableData = normalizePaletteLUTToFinal(redPaletteColorLookupTableData, result.redPaletteColorLookupTableDescriptor, 'red');
|
|
111
|
+
result.greenPaletteColorLookupTableData = normalizePaletteLUTToFinal(greenPaletteColorLookupTableData, result.greenPaletteColorLookupTableDescriptor, 'green');
|
|
112
|
+
result.bluePaletteColorLookupTableData = normalizePaletteLUTToFinal(bluePaletteColorLookupTableData, result.bluePaletteColorLookupTableDescriptor, 'blue');
|
|
113
|
+
}
|
|
114
|
+
if (pixelRepresentation == 1) {
|
|
115
|
+
if (pixelPaddingValue < 0) {
|
|
116
|
+
result.pixelPaddingValue = pixelPaddingValue & 0xffff;
|
|
117
|
+
}
|
|
118
|
+
if (pixelPaddingRangeLimit < 0) {
|
|
119
|
+
result.pixelPaddingValue = pixelPaddingRangeLimit & 0xffff;
|
|
120
|
+
}
|
|
121
|
+
const { smallestPixelValue, largestPixelValue } = result;
|
|
122
|
+
if (smallestPixelValue < 0) {
|
|
123
|
+
result.smallestPixelValue = smallestPixelValue & 0xffff;
|
|
124
|
+
}
|
|
125
|
+
if (largestPixelValue < 0) {
|
|
126
|
+
result.largestPixelValue = largestPixelValue & 0xffff;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
export function registerPixelDataUpdate() {
|
|
132
|
+
addTypedProvider(MetadataModules.IMAGE_PIXEL, pixelDataUpdate);
|
|
133
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerScalingFromInstanceProvider(): void;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { addTypedProvider } from '../../metaData';
|
|
2
|
+
import { MetadataModules } from '../../enums';
|
|
3
|
+
import { calculateSUVScalingFactors } from '@cornerstonejs/calculate-suv';
|
|
4
|
+
function timeToString(v) {
|
|
5
|
+
if (typeof v === 'string')
|
|
6
|
+
return v;
|
|
7
|
+
if (v && typeof v === 'object' && !Array.isArray(v)) {
|
|
8
|
+
const t = v;
|
|
9
|
+
const hours = `${t?.hours ?? '00'}`.padStart(2, '0');
|
|
10
|
+
const minutes = `${t?.minutes ?? '00'}`.padStart(2, '0');
|
|
11
|
+
const seconds = `${t?.seconds ?? '00'}`.padStart(2, '0');
|
|
12
|
+
const fractionalSeconds = `${t?.fractionalSeconds ?? '000000'}`.padEnd(6, '0');
|
|
13
|
+
return `${hours}${minutes}${seconds}.${fractionalSeconds}`;
|
|
14
|
+
}
|
|
15
|
+
return v;
|
|
16
|
+
}
|
|
17
|
+
function dateToString(v) {
|
|
18
|
+
if (typeof v === 'string')
|
|
19
|
+
return v;
|
|
20
|
+
if (v && typeof v === 'object' && !Array.isArray(v) && 'year' in v) {
|
|
21
|
+
const d = v;
|
|
22
|
+
const month = `${d.month}`.padStart(2, '0');
|
|
23
|
+
const day = `${d.day}`.padStart(2, '0');
|
|
24
|
+
return `${d.year}${month}${day}`;
|
|
25
|
+
}
|
|
26
|
+
return v;
|
|
27
|
+
}
|
|
28
|
+
function parseNumber(v) {
|
|
29
|
+
if (typeof v === 'number' && !Number.isNaN(v))
|
|
30
|
+
return v;
|
|
31
|
+
if (typeof v === 'string') {
|
|
32
|
+
const n = Number(v);
|
|
33
|
+
return Number.isNaN(n) ? undefined : n;
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
function getRadiopharmaceuticalInfo(data) {
|
|
38
|
+
const ri = data.RadiopharmaceuticalInfo;
|
|
39
|
+
if (ri == null || typeof ri !== 'object')
|
|
40
|
+
return undefined;
|
|
41
|
+
const first = Array.isArray(ri)
|
|
42
|
+
? ri[0]
|
|
43
|
+
: (ri[0] ?? ri);
|
|
44
|
+
return first && typeof first === 'object' && !Array.isArray(first)
|
|
45
|
+
? first
|
|
46
|
+
: undefined;
|
|
47
|
+
}
|
|
48
|
+
function buildPTInstanceMetadataFromData(data) {
|
|
49
|
+
if (data.Modality !== 'PT')
|
|
50
|
+
return null;
|
|
51
|
+
const { SeriesDate: seriesDate, SeriesTime: seriesTime, AcquisitionDate: acquisitionDate, AcquisitionTime: acquisitionTime, PatientWeight: patientWeight, CorrectedImage: correctedImage, Units: units, DecayCorrection: decayCorrection, } = data;
|
|
52
|
+
const ri = getRadiopharmaceuticalInfo(data);
|
|
53
|
+
if (!ri)
|
|
54
|
+
return null;
|
|
55
|
+
const radionuclideTotalDose = parseNumber(ri.RadionuclideTotalDose);
|
|
56
|
+
const radionuclideHalfLife = parseNumber(ri.RadionuclideHalfLife);
|
|
57
|
+
const radiopharmaceuticalStartDateTime = ri.RadiopharmaceuticalStartDateTime;
|
|
58
|
+
const radiopharmaceuticalStartTime = ri.RadiopharmaceuticalStartTime;
|
|
59
|
+
const patientWeightNum = parseNumber(patientWeight);
|
|
60
|
+
if (seriesDate === undefined ||
|
|
61
|
+
seriesTime === undefined ||
|
|
62
|
+
patientWeightNum === undefined ||
|
|
63
|
+
acquisitionDate === undefined ||
|
|
64
|
+
acquisitionTime === undefined ||
|
|
65
|
+
correctedImage === undefined ||
|
|
66
|
+
units === undefined ||
|
|
67
|
+
decayCorrection === undefined ||
|
|
68
|
+
radionuclideTotalDose === undefined ||
|
|
69
|
+
radionuclideHalfLife === undefined) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const toDate = (v) => typeof v === 'string'
|
|
73
|
+
? v
|
|
74
|
+
: v && typeof v === 'object' && 'year' in v
|
|
75
|
+
? dateToString(v)
|
|
76
|
+
: v;
|
|
77
|
+
const toTime = (v) => typeof v === 'string'
|
|
78
|
+
? v
|
|
79
|
+
: v && typeof v === 'object'
|
|
80
|
+
? timeToString(v)
|
|
81
|
+
: v;
|
|
82
|
+
const correctedImageValue = typeof correctedImage === 'string'
|
|
83
|
+
? correctedImage.split('\\')
|
|
84
|
+
: Array.isArray(correctedImage)
|
|
85
|
+
? correctedImage
|
|
86
|
+
: correctedImage;
|
|
87
|
+
const instanceMetadata = {
|
|
88
|
+
CorrectedImage: correctedImageValue,
|
|
89
|
+
Units: units,
|
|
90
|
+
RadionuclideHalfLife: radionuclideHalfLife,
|
|
91
|
+
RadionuclideTotalDose: radionuclideTotalDose,
|
|
92
|
+
DecayCorrection: decayCorrection,
|
|
93
|
+
PatientWeight: patientWeightNum,
|
|
94
|
+
SeriesDate: dateToString(seriesDate),
|
|
95
|
+
SeriesTime: timeToString(seriesTime),
|
|
96
|
+
AcquisitionDate: dateToString(acquisitionDate),
|
|
97
|
+
AcquisitionTime: timeToString(acquisitionTime),
|
|
98
|
+
};
|
|
99
|
+
if (radiopharmaceuticalStartDateTime !== undefined) {
|
|
100
|
+
instanceMetadata.RadiopharmaceuticalStartDateTime = dateToString(radiopharmaceuticalStartDateTime);
|
|
101
|
+
}
|
|
102
|
+
if (radiopharmaceuticalStartTime !== undefined) {
|
|
103
|
+
instanceMetadata.RadiopharmaceuticalStartTime = timeToString(radiopharmaceuticalStartTime);
|
|
104
|
+
}
|
|
105
|
+
if (data.PatientSex !== undefined)
|
|
106
|
+
instanceMetadata.PatientSex = data.PatientSex;
|
|
107
|
+
if (data.PatientSize !== undefined)
|
|
108
|
+
instanceMetadata.PatientSize = data.PatientSize;
|
|
109
|
+
return instanceMetadata;
|
|
110
|
+
}
|
|
111
|
+
function scalingFromInstanceProvider(next, query, data, options) {
|
|
112
|
+
if (data == null || typeof data !== 'object') {
|
|
113
|
+
return next(query, data, options);
|
|
114
|
+
}
|
|
115
|
+
const d = data;
|
|
116
|
+
if (d.Modality === 'RTDOSE') {
|
|
117
|
+
const doseGridScaling = parseNumber(d.DoseGridScaling);
|
|
118
|
+
const { DoseSummation, DoseType, DoseUnit } = d;
|
|
119
|
+
if (doseGridScaling !== undefined ||
|
|
120
|
+
DoseSummation !== undefined ||
|
|
121
|
+
DoseType !== undefined ||
|
|
122
|
+
DoseUnit !== undefined) {
|
|
123
|
+
return {
|
|
124
|
+
DoseGridScaling: doseGridScaling,
|
|
125
|
+
DoseSummation,
|
|
126
|
+
DoseType,
|
|
127
|
+
DoseUnit,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (d.Modality === 'PT') {
|
|
132
|
+
const instanceMetadata = buildPTInstanceMetadataFromData(d);
|
|
133
|
+
if (!instanceMetadata) {
|
|
134
|
+
return next(query, undefined, options);
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const factors = calculateSUVScalingFactors([instanceMetadata]);
|
|
138
|
+
return factors[0] ?? next(query, undefined, options);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return next(query, undefined, options);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return next(query, undefined, options);
|
|
145
|
+
}
|
|
146
|
+
export function registerScalingFromInstanceProvider() {
|
|
147
|
+
addTypedProvider(MetadataModules.SCALING, scalingFromInstanceProvider, { priority: 0, isDefault: true });
|
|
148
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type TypedProvider } from '../../metaData';
|
|
2
|
+
export declare function clearTagModules(): void;
|
|
3
|
+
export declare function tagModules(module: string, dataLookupName?: string): TypedProvider;
|
|
4
|
+
export declare const MODULE_PRIORITY: {
|
|
5
|
+
priority: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function registerTagModules(): void;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { addTypedProvider } from '../../metaData';
|
|
2
|
+
import { mapModuleTags } from '../Tags';
|
|
3
|
+
import { dataLookup, DATA_PRIORITY, instanceLookup } from './dataLookup';
|
|
4
|
+
import { makeArrayLike } from './makeArrayLike';
|
|
5
|
+
import { metadataLog } from '../logging';
|
|
6
|
+
const log = metadataLog.getLogger('tagModules');
|
|
7
|
+
const mapModules = new Map();
|
|
8
|
+
export function clearTagModules() {
|
|
9
|
+
mapModules.clear();
|
|
10
|
+
}
|
|
11
|
+
export function tagModules(module, dataLookupName = 'instance') {
|
|
12
|
+
if (!mapModuleTags.has(module)) {
|
|
13
|
+
throw new Error(`No module found: ${module}`);
|
|
14
|
+
}
|
|
15
|
+
if (mapModules.has(module)) {
|
|
16
|
+
return mapModules.get(module);
|
|
17
|
+
}
|
|
18
|
+
if (dataLookupName === 'instance') {
|
|
19
|
+
addTypedProvider(module, instanceLookup, { priority: 25_000 });
|
|
20
|
+
}
|
|
21
|
+
else if (dataLookupName) {
|
|
22
|
+
addTypedProvider(module, dataLookup(dataLookupName), { priority: 25_000 });
|
|
23
|
+
}
|
|
24
|
+
const moduleProvider = (next, query, data, options) => {
|
|
25
|
+
const keys = mapModuleTags.get(module);
|
|
26
|
+
const destName = options?.destName || 'lowerName';
|
|
27
|
+
if (!data) {
|
|
28
|
+
return next(query, data, options);
|
|
29
|
+
}
|
|
30
|
+
const result = {};
|
|
31
|
+
for (const key of keys) {
|
|
32
|
+
let value = data[key.name];
|
|
33
|
+
if (value !== undefined) {
|
|
34
|
+
if (mapModules.has(key.name)) {
|
|
35
|
+
log.debug('Getting nested module', key.name);
|
|
36
|
+
const newValue = [];
|
|
37
|
+
for (const entry of value) {
|
|
38
|
+
if (!entry) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
newValue.push(mapModules.get(key.name)(null, query, entry, options?.[key.name]));
|
|
42
|
+
}
|
|
43
|
+
value = newValue.length === 1 ? makeArrayLike(newValue[0]) : newValue;
|
|
44
|
+
}
|
|
45
|
+
result[key[destName]] = value;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
mapModules.set(module, moduleProvider);
|
|
51
|
+
return moduleProvider;
|
|
52
|
+
}
|
|
53
|
+
export const MODULE_PRIORITY = { priority: -1_000 };
|
|
54
|
+
export function registerTagModules() {
|
|
55
|
+
for (const module of mapModuleTags.keys()) {
|
|
56
|
+
const providerFn = tagModules(module);
|
|
57
|
+
if (providerFn) {
|
|
58
|
+
addTypedProvider(module, providerFn, MODULE_PRIORITY);
|
|
59
|
+
}
|
|
60
|
+
addTypedProvider(module, instanceLookup, DATA_PRIORITY);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { MetadataModules } from '../../enums';
|
|
2
|
+
import { addTypedProvider } from '../../metaData';
|
|
3
|
+
import isVideoTransferSyntax from '../isVideoTransferSyntax';
|
|
4
|
+
export function transferSyntaxProvider(next, query, data, options) {
|
|
5
|
+
const fmiBase = next(query, data, options);
|
|
6
|
+
if (fmiBase) {
|
|
7
|
+
const transferSyntaxUID = fmiBase.transferSyntaxUID || fmiBase.availableTransferSyntaxUID;
|
|
8
|
+
const isVideo = isVideoTransferSyntax(transferSyntaxUID);
|
|
9
|
+
return {
|
|
10
|
+
...fmiBase,
|
|
11
|
+
transferSyntaxUID: Array.isArray(transferSyntaxUID)
|
|
12
|
+
? transferSyntaxUID[0]
|
|
13
|
+
: transferSyntaxUID,
|
|
14
|
+
isVideo,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function registerTransferSyntaxProvider() {
|
|
19
|
+
addTypedProvider(MetadataModules.TRANSFER_SYNTAX, transferSyntaxProvider);
|
|
20
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface UriModule {
|
|
2
|
+
baseImageId: string;
|
|
3
|
+
frameNumber?: number;
|
|
4
|
+
framesString?: string;
|
|
5
|
+
remaining?: string;
|
|
6
|
+
sopInstanceUID?: string;
|
|
7
|
+
seriesInstanceUID?: string;
|
|
8
|
+
studyInstanceUID?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const frameRangeExtractor: RegExp;
|
|
11
|
+
export declare function getUriModule(imageId: any): {
|
|
12
|
+
baseImageId: any;
|
|
13
|
+
frameNumber: number;
|
|
14
|
+
framesString: any;
|
|
15
|
+
remaining: any;
|
|
16
|
+
};
|
|
17
|
+
export declare function uriModuleProvider(next: any, imageId: any, data: any, options: any): any;
|
|
18
|
+
export declare function registerUriModule(): void;
|
|
19
|
+
export default getUriModule;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { MetadataModules } from '../../enums';
|
|
2
|
+
import { addTypedProvider } from '../../metaData';
|
|
3
|
+
export const frameRangeExtractor = /(\/frames\/|[&?]frameNumber=|[&?]frame=)([^/&?]*)(.*)/i;
|
|
4
|
+
export function getUriModule(imageId) {
|
|
5
|
+
const framesMatch = imageId.match(frameRangeExtractor);
|
|
6
|
+
if (!framesMatch) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const baseImageId = imageId.substring(0, framesMatch.index);
|
|
10
|
+
const framesString = framesMatch[2];
|
|
11
|
+
const frameNumber = parseFloat(framesString);
|
|
12
|
+
const remaining = framesMatch[3];
|
|
13
|
+
return {
|
|
14
|
+
baseImageId,
|
|
15
|
+
frameNumber,
|
|
16
|
+
framesString,
|
|
17
|
+
remaining,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function uriModuleProvider(next, imageId, data, options) {
|
|
21
|
+
return getUriModule(imageId) || next(imageId, data, options);
|
|
22
|
+
}
|
|
23
|
+
export function registerUriModule() {
|
|
24
|
+
addTypedProvider(MetadataModules.URI_MODULE, uriModuleProvider);
|
|
25
|
+
}
|
|
26
|
+
export default getUriModule;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const tags = [
|
|
2
|
+
'SOPInstanceUID',
|
|
3
|
+
'SOPClassUID',
|
|
4
|
+
'InstanceNumber',
|
|
5
|
+
'InstanceCreationDate',
|
|
6
|
+
'InstanceCreationTime',
|
|
7
|
+
'ContentTime',
|
|
8
|
+
'LossyImageCompression',
|
|
9
|
+
'LossyImageCompressionRatio',
|
|
10
|
+
'LossyImageCompressionMethod',
|
|
11
|
+
'FrameOfReferenceUID',
|
|
12
|
+
'NumberOfFrames',
|
|
13
|
+
'PixelSpacing',
|
|
14
|
+
];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const tags = [
|
|
2
|
+
'SamplesPerPixel',
|
|
3
|
+
'PhotometricInterpretation',
|
|
4
|
+
'PlanarConfiguration',
|
|
5
|
+
'Rows',
|
|
6
|
+
'Columns',
|
|
7
|
+
'BitsAllocated',
|
|
8
|
+
'BitsStored',
|
|
9
|
+
'HighBit',
|
|
10
|
+
'PixelRepresentation',
|
|
11
|
+
['SmallestPixelValue', '00280106'],
|
|
12
|
+
['LargestPixelValue', '00280107'],
|
|
13
|
+
'PixelPaddingValue',
|
|
14
|
+
'PixelPaddingRangeLimit',
|
|
15
|
+
'RedPaletteColorLookupTableDescriptor',
|
|
16
|
+
'GreenPaletteColorLookupTableDescriptor',
|
|
17
|
+
'BluePaletteColorLookupTableDescriptor',
|
|
18
|
+
'AlphaPaletteColorLookupTableDescriptor',
|
|
19
|
+
'RedPaletteColorLookupTableData',
|
|
20
|
+
'GreenPaletteColorLookupTableData',
|
|
21
|
+
'BluePaletteColorLookupTableData',
|
|
22
|
+
'AlphaPaletteColorLookupTableData',
|
|
23
|
+
'PaletteColorLookupTableUID',
|
|
24
|
+
'DistanceSourceToDetector',
|
|
25
|
+
'DistanceSourceToPatient',
|
|
26
|
+
'EstimatedRadiographicMagnificationFactor',
|
|
27
|
+
'DistanceSourceToEntrance',
|
|
28
|
+
'PixelSpacingCalibrationType',
|
|
29
|
+
'PixelSpacingCalibrationDescription',
|
|
30
|
+
'SequenceOfUltrasoundRegions',
|
|
31
|
+
];
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const USRegionChild = "usRegionChild";
|
|
2
|
+
export declare const CLINICAL_TRIAL = "clinicalTrialModule";
|
|
3
|
+
export declare const RadiopharmaceuticalInfoModule = "RadiopharmaceuticalInfo";
|
|
4
|
+
export type ModuleTagEntry = string | [name: string, hexOverride: string];
|
|
5
|
+
export declare const moduleDefinitions: [string | null, ModuleTagEntry[]][];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { MetadataModules } from '../../enums';
|
|
2
|
+
import { tags as transferSyntaxTags } from './transferSyntax';
|
|
3
|
+
import { tags as cineTags } from './cine';
|
|
4
|
+
import { tags as ptIsotopeTags } from './ptIsotope';
|
|
5
|
+
import { tags as radiopharmaceuticalInfoTags } from './radiopharmaceuticalInfo';
|
|
6
|
+
import { tags as ptImageTags } from './ptImage';
|
|
7
|
+
import { tags as ptSeriesTags } from './ptSeries';
|
|
8
|
+
import { tags as patientTags } from './patient';
|
|
9
|
+
import { tags as patientStudyTags } from './patientStudy';
|
|
10
|
+
import { tags as generalStudyTags } from './generalStudy';
|
|
11
|
+
import { tags as generalSeriesTags } from './generalSeries';
|
|
12
|
+
import { tags as clinicalTrialTags } from './clinicalTrial';
|
|
13
|
+
import { tags as sopCommonTags } from './sopCommon';
|
|
14
|
+
import { tags as ecgTags } from './ecg';
|
|
15
|
+
import { tags as generalImageTags } from './generalImage';
|
|
16
|
+
import { tags as imagePlaneTags } from './imagePlane';
|
|
17
|
+
import { tags as imagePixelTags } from './imagePixel';
|
|
18
|
+
import { tags as voiLutTags } from './voiLut';
|
|
19
|
+
import { tags as modalityLutTags } from './modalityLut';
|
|
20
|
+
import { tags as ultrasoundEnhancedRegionTags } from './ultrasoundEnhancedRegion';
|
|
21
|
+
import { tags as usRegionChildTags } from './usRegionChild';
|
|
22
|
+
import { tags as unassignedTags } from './unassigned';
|
|
23
|
+
export const USRegionChild = 'usRegionChild';
|
|
24
|
+
export const CLINICAL_TRIAL = 'clinicalTrialModule';
|
|
25
|
+
export const RadiopharmaceuticalInfoModule = 'RadiopharmaceuticalInfo';
|
|
26
|
+
export const moduleDefinitions = [
|
|
27
|
+
[MetadataModules.TRANSFER_SYNTAX, transferSyntaxTags],
|
|
28
|
+
[MetadataModules.CINE, cineTags],
|
|
29
|
+
[MetadataModules.PET_ISOTOPE, ptIsotopeTags],
|
|
30
|
+
[RadiopharmaceuticalInfoModule, radiopharmaceuticalInfoTags],
|
|
31
|
+
[MetadataModules.PET_IMAGE, ptImageTags],
|
|
32
|
+
[MetadataModules.PET_SERIES, ptSeriesTags],
|
|
33
|
+
[MetadataModules.PATIENT, patientTags],
|
|
34
|
+
[MetadataModules.PATIENT_STUDY, patientStudyTags],
|
|
35
|
+
[MetadataModules.GENERAL_STUDY, generalStudyTags],
|
|
36
|
+
[MetadataModules.GENERAL_SERIES, generalSeriesTags],
|
|
37
|
+
[CLINICAL_TRIAL, clinicalTrialTags],
|
|
38
|
+
[MetadataModules.SOP_COMMON, sopCommonTags],
|
|
39
|
+
[MetadataModules.ECG, ecgTags],
|
|
40
|
+
[MetadataModules.GENERAL_IMAGE, generalImageTags],
|
|
41
|
+
[MetadataModules.IMAGE_PLANE, imagePlaneTags],
|
|
42
|
+
[MetadataModules.IMAGE_PIXEL, imagePixelTags],
|
|
43
|
+
[MetadataModules.VOI_LUT, voiLutTags],
|
|
44
|
+
[MetadataModules.MODALITY_LUT, modalityLutTags],
|
|
45
|
+
[MetadataModules.ULTRASOUND_ENHANCED_REGION, ultrasoundEnhancedRegionTags],
|
|
46
|
+
[USRegionChild, usRegionChildTags],
|
|
47
|
+
[null, unassignedTags],
|
|
48
|
+
];
|