@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.
Files changed (138) hide show
  1. package/LICENSE +21 -0
  2. package/dist/esm/enums/CalibrationTypes.d.ts +12 -0
  3. package/dist/esm/enums/CalibrationTypes.js +13 -0
  4. package/dist/esm/enums/MetadataModules.d.ts +54 -0
  5. package/dist/esm/enums/MetadataModules.js +57 -0
  6. package/dist/esm/enums/index.d.ts +4 -0
  7. package/dist/esm/enums/index.js +4 -0
  8. package/dist/esm/index.d.ts +10 -0
  9. package/dist/esm/index.js +9 -0
  10. package/dist/esm/metaData.d.ts +33 -0
  11. package/dist/esm/metaData.js +181 -0
  12. package/dist/esm/registerDefaultProviders.d.ts +1 -0
  13. package/dist/esm/registerDefaultProviders.js +38 -0
  14. package/dist/esm/types/DicomStreamTypes.d.ts +13 -0
  15. package/dist/esm/types/DicomStreamTypes.js +0 -0
  16. package/dist/esm/types/IImageCalibration.d.ts +11 -0
  17. package/dist/esm/types/IImageCalibration.js +0 -0
  18. package/dist/esm/types/MetadataModuleTypes.d.ts +100 -0
  19. package/dist/esm/types/MetadataModuleTypes.js +0 -0
  20. package/dist/esm/types/index.d.ts +3 -0
  21. package/dist/esm/types/index.js +0 -0
  22. package/dist/esm/utilities/Tags.d.ts +25 -0
  23. package/dist/esm/utilities/Tags.js +112 -0
  24. package/dist/esm/utilities/bulkDataFromArray.d.ts +1 -0
  25. package/dist/esm/utilities/bulkDataFromArray.js +38 -0
  26. package/dist/esm/utilities/calibratedPixelSpacingMetadataProvider.d.ts +7 -0
  27. package/dist/esm/utilities/calibratedPixelSpacingMetadataProvider.js +21 -0
  28. package/dist/esm/utilities/dicomStream/MetaDataIterator.d.ts +11 -0
  29. package/dist/esm/utilities/dicomStream/MetaDataIterator.js +58 -0
  30. package/dist/esm/utilities/dicomStream/NaturalTagListener.d.ts +22 -0
  31. package/dist/esm/utilities/dicomStream/NaturalTagListener.js +106 -0
  32. package/dist/esm/utilities/dicomStream/index.d.ts +3 -0
  33. package/dist/esm/utilities/dicomStream/index.js +2 -0
  34. package/dist/esm/utilities/getNaturalizedField.d.ts +3 -0
  35. package/dist/esm/utilities/getNaturalizedField.js +34 -0
  36. package/dist/esm/utilities/getPixelSpacingInformation.d.ts +13 -0
  37. package/dist/esm/utilities/getPixelSpacingInformation.js +93 -0
  38. package/dist/esm/utilities/imageIdToURI.d.ts +1 -0
  39. package/dist/esm/utilities/imageIdToURI.js +15 -0
  40. package/dist/esm/utilities/index.d.ts +15 -0
  41. package/dist/esm/utilities/index.js +15 -0
  42. package/dist/esm/utilities/isEqual.d.ts +2 -0
  43. package/dist/esm/utilities/isEqual.js +2 -0
  44. package/dist/esm/utilities/isVideoTransferSyntax.d.ts +2 -0
  45. package/dist/esm/utilities/isVideoTransferSyntax.js +25 -0
  46. package/dist/esm/utilities/logging.d.ts +3 -0
  47. package/dist/esm/utilities/logging.js +2 -0
  48. package/dist/esm/utilities/metadataProvider/addDicomPart10Instance.d.ts +2 -0
  49. package/dist/esm/utilities/metadataProvider/addDicomPart10Instance.js +12 -0
  50. package/dist/esm/utilities/metadataProvider/cacheData.d.ts +39 -0
  51. package/dist/esm/utilities/metadataProvider/cacheData.js +235 -0
  52. package/dist/esm/utilities/metadataProvider/calibrationModule.d.ts +2 -0
  53. package/dist/esm/utilities/metadataProvider/calibrationModule.js +25 -0
  54. package/dist/esm/utilities/metadataProvider/combineFrameInstance.d.ts +5 -0
  55. package/dist/esm/utilities/metadataProvider/combineFrameInstance.js +158 -0
  56. package/dist/esm/utilities/metadataProvider/compressedFrameData.d.ts +1 -0
  57. package/dist/esm/utilities/metadataProvider/compressedFrameData.js +133 -0
  58. package/dist/esm/utilities/metadataProvider/dataLookup.d.ts +7 -0
  59. package/dist/esm/utilities/metadataProvider/dataLookup.js +18 -0
  60. package/dist/esm/utilities/metadataProvider/dicomSplit.d.ts +1 -0
  61. package/dist/esm/utilities/metadataProvider/dicomSplit.js +5 -0
  62. package/dist/esm/utilities/metadataProvider/ecgFromInstance.d.ts +18 -0
  63. package/dist/esm/utilities/metadataProvider/ecgFromInstance.js +228 -0
  64. package/dist/esm/utilities/metadataProvider/ecgModule.d.ts +1 -0
  65. package/dist/esm/utilities/metadataProvider/ecgModule.js +0 -0
  66. package/dist/esm/utilities/metadataProvider/imageIdsProviders.d.ts +11 -0
  67. package/dist/esm/utilities/metadataProvider/imageIdsProviders.js +117 -0
  68. package/dist/esm/utilities/metadataProvider/imagePlaneCalibrated.d.ts +4 -0
  69. package/dist/esm/utilities/metadataProvider/imagePlaneCalibrated.js +89 -0
  70. package/dist/esm/utilities/metadataProvider/index.d.ts +18 -0
  71. package/dist/esm/utilities/metadataProvider/index.js +17 -0
  72. package/dist/esm/utilities/metadataProvider/instanceFromListener.d.ts +2 -0
  73. package/dist/esm/utilities/metadataProvider/instanceFromListener.js +9 -0
  74. package/dist/esm/utilities/metadataProvider/makeArrayLike.d.ts +1 -0
  75. package/dist/esm/utilities/metadataProvider/makeArrayLike.js +25 -0
  76. package/dist/esm/utilities/metadataProvider/naturalizedHandlers.d.ts +5 -0
  77. package/dist/esm/utilities/metadataProvider/naturalizedHandlers.js +67 -0
  78. package/dist/esm/utilities/metadataProvider/pixelDataUpdate.d.ts +2 -0
  79. package/dist/esm/utilities/metadataProvider/pixelDataUpdate.js +133 -0
  80. package/dist/esm/utilities/metadataProvider/scalingFromInstance.d.ts +1 -0
  81. package/dist/esm/utilities/metadataProvider/scalingFromInstance.js +148 -0
  82. package/dist/esm/utilities/metadataProvider/tagModules.d.ts +7 -0
  83. package/dist/esm/utilities/metadataProvider/tagModules.js +62 -0
  84. package/dist/esm/utilities/metadataProvider/transferSyntaxProvider.d.ts +2 -0
  85. package/dist/esm/utilities/metadataProvider/transferSyntaxProvider.js +20 -0
  86. package/dist/esm/utilities/metadataProvider/uriModule.d.ts +19 -0
  87. package/dist/esm/utilities/metadataProvider/uriModule.js +26 -0
  88. package/dist/esm/utilities/modules/cine.d.ts +2 -0
  89. package/dist/esm/utilities/modules/cine.js +4 -0
  90. package/dist/esm/utilities/modules/clinicalTrial.d.ts +2 -0
  91. package/dist/esm/utilities/modules/clinicalTrial.js +6 -0
  92. package/dist/esm/utilities/modules/ecg.d.ts +2 -0
  93. package/dist/esm/utilities/modules/ecg.js +11 -0
  94. package/dist/esm/utilities/modules/generalImage.d.ts +2 -0
  95. package/dist/esm/utilities/modules/generalImage.js +14 -0
  96. package/dist/esm/utilities/modules/generalSeries.d.ts +2 -0
  97. package/dist/esm/utilities/modules/generalSeries.js +11 -0
  98. package/dist/esm/utilities/modules/generalStudy.d.ts +2 -0
  99. package/dist/esm/utilities/modules/generalStudy.js +7 -0
  100. package/dist/esm/utilities/modules/imagePixel.d.ts +2 -0
  101. package/dist/esm/utilities/modules/imagePixel.js +31 -0
  102. package/dist/esm/utilities/modules/imagePlane.d.ts +2 -0
  103. package/dist/esm/utilities/modules/imagePlane.js +8 -0
  104. package/dist/esm/utilities/modules/index.d.ts +5 -0
  105. package/dist/esm/utilities/modules/index.js +48 -0
  106. package/dist/esm/utilities/modules/modalityLut.d.ts +2 -0
  107. package/dist/esm/utilities/modules/modalityLut.js +5 -0
  108. package/dist/esm/utilities/modules/patient.d.ts +2 -0
  109. package/dist/esm/utilities/modules/patient.js +6 -0
  110. package/dist/esm/utilities/modules/patientStudy.d.ts +2 -0
  111. package/dist/esm/utilities/modules/patientStudy.js +6 -0
  112. package/dist/esm/utilities/modules/ptImage.d.ts +2 -0
  113. package/dist/esm/utilities/modules/ptImage.js +4 -0
  114. package/dist/esm/utilities/modules/ptIsotope.d.ts +2 -0
  115. package/dist/esm/utilities/modules/ptIsotope.js +1 -0
  116. package/dist/esm/utilities/modules/ptSeries.d.ts +2 -0
  117. package/dist/esm/utilities/modules/ptSeries.js +5 -0
  118. package/dist/esm/utilities/modules/radiopharmaceuticalInfo.d.ts +2 -0
  119. package/dist/esm/utilities/modules/radiopharmaceuticalInfo.js +6 -0
  120. package/dist/esm/utilities/modules/sopCommon.d.ts +2 -0
  121. package/dist/esm/utilities/modules/sopCommon.js +1 -0
  122. package/dist/esm/utilities/modules/transferSyntax.d.ts +2 -0
  123. package/dist/esm/utilities/modules/transferSyntax.js +4 -0
  124. package/dist/esm/utilities/modules/ultrasoundEnhancedRegion.d.ts +2 -0
  125. package/dist/esm/utilities/modules/ultrasoundEnhancedRegion.js +1 -0
  126. package/dist/esm/utilities/modules/unassigned.d.ts +2 -0
  127. package/dist/esm/utilities/modules/unassigned.js +15 -0
  128. package/dist/esm/utilities/modules/usRegionChild.d.ts +2 -0
  129. package/dist/esm/utilities/modules/usRegionChild.js +18 -0
  130. package/dist/esm/utilities/modules/voiLut.d.ts +2 -0
  131. package/dist/esm/utilities/modules/voiLut.js +6 -0
  132. package/dist/esm/utilities/splitImageIdsBy4DTags.d.ts +12 -0
  133. package/dist/esm/utilities/splitImageIdsBy4DTags.js +314 -0
  134. package/dist/esm/utilities/toNumber.d.ts +2 -0
  135. package/dist/esm/utilities/toNumber.js +2 -0
  136. package/dist/esm/version.d.ts +1 -0
  137. package/dist/esm/version.js +1 -0
  138. package/package.json +99 -0
@@ -0,0 +1,39 @@
1
+ interface CacheGetOptions {
2
+ noCache?: boolean;
3
+ reCache?: boolean;
4
+ }
5
+ export declare class CacheData {
6
+ protected static readonly mapCacheData: Map<string, Map<string, unknown>>;
7
+ protected static readonly secondaryTypesByBaseType: Map<string, Set<string>>;
8
+ protected static setCacheDataInternal(type: string, query: string, value: unknown): void;
9
+ protected static clearRelatedDerivedCache(type: string, query: string): void;
10
+ static registerSecondaryTypes(secondaryType: string, secondaryOf?: string | string[]): void;
11
+ static getCacheData(type: string, query: string): unknown;
12
+ static hasCacheData(type: string, query: string): boolean;
13
+ static clearCacheData(): void;
14
+ static clearTypedCacheData(type: string, query?: string): void;
15
+ static fromAsyncLookup<T>(type: string, query: string, lookup: () => T | Promise<T>, options?: CacheGetOptions): T | Promise<T> | undefined;
16
+ createTypeCacheProvider(type: string): (next: any, query: string, data: any, options: any) => any;
17
+ clearCacheData(): void;
18
+ clearTypedCacheData(type: string, query?: string): void;
19
+ getCacheData(type: string, query: string): unknown;
20
+ hasCacheData(type: string, query: string): boolean;
21
+ fromAsyncLookup<T>(type: string, query: string, lookup: () => T | Promise<T>, options?: CacheGetOptions): T | Promise<T>;
22
+ }
23
+ export declare class WritableCacheData extends CacheData {
24
+ static setCacheData(type: string, query: string, value: unknown): void;
25
+ setCacheData(type: string, query: string, value: unknown): void;
26
+ }
27
+ export declare const cacheData: CacheData;
28
+ export declare function createTypeCacheProvider(type: string): (next: any, query: string, data: any, options: any) => any;
29
+ export declare function createTypeWritableCacheProvider(type: string): (next: any, query: string, data: any, options: any) => any;
30
+ export declare function clearCacheData(): void;
31
+ export declare function clearTypedCacheData(type: string, query?: string): void;
32
+ export declare function setCacheData(type: string, query: string, value: unknown): void;
33
+ export declare function getCacheData(type: string, query: string): unknown;
34
+ export declare function hasCacheData(type: string, query: string): boolean;
35
+ export declare function fromAsyncLookup<T>(type: string, query: string, lookup: () => T | Promise<T>, options?: CacheGetOptions): T | Promise<T>;
36
+ export declare function addCacheForType(type: string, options?: any): void;
37
+ export declare function addWritableCacheForType(type: string, options?: any): void;
38
+ export declare function registerCacheProviders(): void;
39
+ export {};
@@ -0,0 +1,235 @@
1
+ import { getAddModuleType, MetadataModules } from '../../enums';
2
+ import { addAddProvider, addTypedProvider, clear, clearQuery, getMetaData, } from '../../metaData';
3
+ import { BASE_IMAGE_ID, FRAME_IMAGE_IDS } from './imageIdsProviders';
4
+ export class CacheData {
5
+ static setCacheDataInternal(type, query, value) {
6
+ let valueMap = this.mapCacheData.get(type);
7
+ if (!valueMap) {
8
+ valueMap = new Map();
9
+ this.mapCacheData.set(type, valueMap);
10
+ }
11
+ valueMap.set(query, value);
12
+ this.clearRelatedDerivedCache(type, query);
13
+ }
14
+ static clearRelatedDerivedCache(type, query) {
15
+ const derivedTypes = this.secondaryTypesByBaseType.get(type);
16
+ if (!derivedTypes?.size) {
17
+ return;
18
+ }
19
+ const frameImageIds = getMetaData(FRAME_IMAGE_IDS, query) ??
20
+ new Set([query]);
21
+ for (const frameImageId of frameImageIds) {
22
+ for (const derivedType of derivedTypes) {
23
+ const typeMap = this.mapCacheData.get(derivedType);
24
+ typeMap?.delete(frameImageId);
25
+ }
26
+ }
27
+ }
28
+ static registerSecondaryTypes(secondaryType, secondaryOf) {
29
+ if (!secondaryOf) {
30
+ return;
31
+ }
32
+ const baseTypes = Array.isArray(secondaryOf) ? secondaryOf : [secondaryOf];
33
+ for (const baseType of baseTypes) {
34
+ let secondaryTypes = this.secondaryTypesByBaseType.get(baseType);
35
+ if (!secondaryTypes) {
36
+ secondaryTypes = new Set();
37
+ this.secondaryTypesByBaseType.set(baseType, secondaryTypes);
38
+ }
39
+ secondaryTypes.add(secondaryType);
40
+ }
41
+ }
42
+ static getCacheData(type, query) {
43
+ return this.mapCacheData.get(type)?.get(query);
44
+ }
45
+ static hasCacheData(type, query) {
46
+ return this.mapCacheData.get(type)?.has(query) === true;
47
+ }
48
+ static clearCacheData() {
49
+ this.mapCacheData.clear();
50
+ this.secondaryTypesByBaseType.clear();
51
+ clear(FRAME_IMAGE_IDS);
52
+ clear(BASE_IMAGE_ID);
53
+ }
54
+ static clearTypedCacheData(type, query) {
55
+ const secondaryTypes = this.secondaryTypesByBaseType.get(type);
56
+ const valueMap = this.mapCacheData.get(type);
57
+ if (query) {
58
+ valueMap?.delete(query);
59
+ if (secondaryTypes?.size) {
60
+ for (const secondaryType of secondaryTypes) {
61
+ this.mapCacheData.get(secondaryType)?.delete(query);
62
+ }
63
+ }
64
+ if (type === MetadataModules.NATURALIZED || secondaryTypes?.size) {
65
+ clearQuery(FRAME_IMAGE_IDS, query);
66
+ clearQuery(BASE_IMAGE_ID, query);
67
+ }
68
+ return;
69
+ }
70
+ valueMap?.clear();
71
+ if (secondaryTypes?.size) {
72
+ for (const secondaryType of secondaryTypes) {
73
+ this.mapCacheData.get(secondaryType)?.clear();
74
+ }
75
+ }
76
+ if (type === MetadataModules.NATURALIZED || secondaryTypes?.size) {
77
+ clear(FRAME_IMAGE_IDS);
78
+ clear(BASE_IMAGE_ID);
79
+ }
80
+ }
81
+ static fromAsyncLookup(type, query, lookup, options) {
82
+ if (options?.noCache !== true && options?.reCache !== true) {
83
+ const cachedValue = this.getCacheData(type, query);
84
+ if (cachedValue !== undefined) {
85
+ return cachedValue;
86
+ }
87
+ }
88
+ const lookupValue = lookup();
89
+ if (lookupValue === undefined) {
90
+ return undefined;
91
+ }
92
+ if (!(lookupValue instanceof Promise)) {
93
+ if (!options?.noCache) {
94
+ this.setCacheDataInternal(type, query, lookupValue);
95
+ }
96
+ return lookupValue;
97
+ }
98
+ return lookupValue.then((resolvedValue) => {
99
+ if (resolvedValue !== undefined && !options?.noCache) {
100
+ this.setCacheDataInternal(type, query, resolvedValue);
101
+ }
102
+ return resolvedValue;
103
+ });
104
+ }
105
+ createTypeCacheProvider(type) {
106
+ return createTypeCacheProvider(type);
107
+ }
108
+ clearCacheData() {
109
+ CacheData.clearCacheData();
110
+ }
111
+ clearTypedCacheData(type, query) {
112
+ CacheData.clearTypedCacheData(type, query);
113
+ }
114
+ getCacheData(type, query) {
115
+ return CacheData.getCacheData(type, query);
116
+ }
117
+ hasCacheData(type, query) {
118
+ return CacheData.hasCacheData(type, query);
119
+ }
120
+ fromAsyncLookup(type, query, lookup, options) {
121
+ return CacheData.fromAsyncLookup(type, query, lookup, options);
122
+ }
123
+ }
124
+ CacheData.mapCacheData = new Map();
125
+ CacheData.secondaryTypesByBaseType = new Map();
126
+ export class WritableCacheData extends CacheData {
127
+ static setCacheData(type, query, value) {
128
+ this.setCacheDataInternal(type, query, value);
129
+ }
130
+ setCacheData(type, query, value) {
131
+ WritableCacheData.setCacheData(type, query, value);
132
+ }
133
+ }
134
+ export const cacheData = new WritableCacheData();
135
+ export function createTypeCacheProvider(type) {
136
+ return (next, query, data, options) => {
137
+ return CacheData.fromAsyncLookup(type, query, () => next(query, data, options), options);
138
+ };
139
+ }
140
+ export function createTypeWritableCacheProvider(type) {
141
+ const addType = getAddModuleType(type);
142
+ return (next, query, data, options) => {
143
+ const cachedValue = CacheData.getCacheData(type, query);
144
+ if (cachedValue !== undefined) {
145
+ console.warn(`Metadata add skipped for "${type}" at query "${query}" because cache already has a value.`);
146
+ return cachedValue;
147
+ }
148
+ const addCachedValue = CacheData.getCacheData(addType, query);
149
+ if (addCachedValue !== undefined) {
150
+ return addCachedValue;
151
+ }
152
+ const nextValue = next(query, data, options);
153
+ if (nextValue === undefined) {
154
+ return undefined;
155
+ }
156
+ if (!(nextValue instanceof Promise)) {
157
+ WritableCacheData.setCacheData(type, query, nextValue);
158
+ return nextValue;
159
+ }
160
+ const managedPromise = nextValue
161
+ .then((resolvedValue) => {
162
+ if (resolvedValue !== undefined) {
163
+ WritableCacheData.setCacheData(type, query, resolvedValue);
164
+ }
165
+ return resolvedValue;
166
+ })
167
+ .finally(() => {
168
+ CacheData.clearTypedCacheData(addType, query);
169
+ });
170
+ WritableCacheData.setCacheData(addType, query, managedPromise);
171
+ return managedPromise;
172
+ };
173
+ }
174
+ export function clearCacheData() {
175
+ CacheData.clearCacheData();
176
+ }
177
+ export function clearTypedCacheData(type, query) {
178
+ CacheData.clearTypedCacheData(type, query);
179
+ }
180
+ export function setCacheData(type, query, value) {
181
+ WritableCacheData.setCacheData(type, query, value);
182
+ }
183
+ export function getCacheData(type, query) {
184
+ return CacheData.getCacheData(type, query);
185
+ }
186
+ export function hasCacheData(type, query) {
187
+ return CacheData.hasCacheData(type, query);
188
+ }
189
+ export function fromAsyncLookup(type, query, lookup, options) {
190
+ return CacheData.fromAsyncLookup(type, query, lookup, options);
191
+ }
192
+ export function addCacheForType(type, options) {
193
+ const { secondaryOf, ...providerOptions } = (options ??
194
+ {});
195
+ CacheData.registerSecondaryTypes(type, secondaryOf);
196
+ addTypedProvider(type, createTypeCacheProvider(type), {
197
+ priority: 50_000,
198
+ clear: clearTypedCacheData.bind(null, type),
199
+ clearQuery: clearTypedCacheData.bind(null, type),
200
+ ...providerOptions,
201
+ });
202
+ }
203
+ export function addWritableCacheForType(type, options) {
204
+ const addType = getAddModuleType(type);
205
+ const { secondaryOf, ...providerOptions } = (options ??
206
+ {});
207
+ addCacheForType(type, { secondaryOf, ...providerOptions });
208
+ CacheData.registerSecondaryTypes(addType, type);
209
+ addAddProvider(type, createTypeWritableCacheProvider(type), {
210
+ priority: 50_000,
211
+ clear: clearTypedCacheData.bind(null, addType),
212
+ clearQuery: clearTypedCacheData.bind(null, addType),
213
+ ...providerOptions,
214
+ });
215
+ }
216
+ export function registerCacheProviders() {
217
+ addCacheForType(BASE_IMAGE_ID);
218
+ addCacheForType(FRAME_IMAGE_IDS);
219
+ addWritableCacheForType(MetadataModules.NATURALIZED);
220
+ addCacheForType(MetadataModules.INSTANCE, {
221
+ secondaryOf: MetadataModules.NATURALIZED,
222
+ });
223
+ addCacheForType(MetadataModules.URI_MODULE, {
224
+ secondaryOf: MetadataModules.NATURALIZED,
225
+ });
226
+ addCacheForType(MetadataModules.IMAGE_PLANE, {
227
+ secondaryOf: MetadataModules.NATURALIZED,
228
+ });
229
+ addCacheForType(MetadataModules.FRAME_MODULE, {
230
+ secondaryOf: MetadataModules.NATURALIZED,
231
+ });
232
+ addCacheForType(MetadataModules.GENERAL_IMAGE, {
233
+ secondaryOf: MetadataModules.NATURALIZED,
234
+ });
235
+ }
@@ -0,0 +1,2 @@
1
+ export declare function calibrationModuleProvider(next: any, query: any, data: any, options: any): any;
2
+ export declare function registerCalibrationModule(): void;
@@ -0,0 +1,25 @@
1
+ import { MetadataModules } from '../../enums';
2
+ import { addTypedProvider, toLowerCamelTag } from '../../metaData';
3
+ export function calibrationModuleProvider(next, query, data, options) {
4
+ if (!data) {
5
+ return next(query, data, options);
6
+ }
7
+ if (!data.SequenceOfUltrasoundRegions?.length) {
8
+ return;
9
+ }
10
+ const { SequenceOfUltrasoundRegions } = data;
11
+ const sequenceOfUltrasoundRegions = [];
12
+ for (const sequenceItem of SequenceOfUltrasoundRegions) {
13
+ const newItem = {};
14
+ sequenceOfUltrasoundRegions.push(newItem);
15
+ for (const [key, value] of Object.entries(sequenceItem)) {
16
+ newItem[toLowerCamelTag(key)] = value;
17
+ }
18
+ }
19
+ return {
20
+ sequenceOfUltrasoundRegions,
21
+ };
22
+ }
23
+ export function registerCalibrationModule() {
24
+ addTypedProvider(MetadataModules.CALIBRATION, calibrationModuleProvider);
25
+ }
@@ -0,0 +1,5 @@
1
+ export declare const combineFrameInstance: (frame: any, instance: any) => any;
2
+ export declare function createCombinedValue(parent: any, functionalGroups: any, key: any): any;
3
+ export declare const combineFrameProvider: (next: any, query: any, instance: any, options: any) => any;
4
+ export declare function registerCombineFrameProvider(): void;
5
+ export default combineFrameInstance;
@@ -0,0 +1,158 @@
1
+ import { vec3 } from 'gl-matrix';
2
+ import { dicomSplit } from './dicomSplit';
3
+ import { addTypedProvider, getMetaData } from '../../metaData';
4
+ import { MetadataModules } from '../../enums';
5
+ import { isEqual } from '../isEqual';
6
+ export const combineFrameInstance = (frame, instance) => {
7
+ const { PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, NumberOfFrames, ImageType, } = instance;
8
+ if (NumberOfFrames < 2) {
9
+ return instance;
10
+ }
11
+ instance.ImageType = dicomSplit(ImageType);
12
+ const frameNumber = Number.parseInt(frame || 1);
13
+ const hasDetectorButMissingSpatialInfo = instance.DetectorInformationSequence &&
14
+ (!instance.ImagePositionPatient || !instance.ImageOrientationPatient);
15
+ if ((PerFrameFunctionalGroupsSequence && SharedFunctionalGroupsSequence) ||
16
+ hasDetectorButMissingSpatialInfo) {
17
+ if (!instance.ImageOrientationPatient &&
18
+ instance.DetectorInformationSequence) {
19
+ instance.ImageOrientationPatient =
20
+ instance.DetectorInformationSequence[0].ImageOrientationPatient;
21
+ }
22
+ const rootImagePositionPatient = instance.ImagePositionPatient;
23
+ let detectorDerivedImagePositionPatient;
24
+ if (!instance.ImagePositionPatient &&
25
+ instance.DetectorInformationSequence) {
26
+ let imagePositionPatient = instance.DetectorInformationSequence[0].ImagePositionPatient;
27
+ let imageOrientationPatient = instance.ImageOrientationPatient;
28
+ imagePositionPatient = imagePositionPatient?.map((it) => Number(it));
29
+ imageOrientationPatient = imageOrientationPatient?.map((it) => Number(it));
30
+ const SpacingBetweenSlices = Number(instance.SpacingBetweenSlices);
31
+ if (imageOrientationPatient && SpacingBetweenSlices) {
32
+ const rowOrientation = vec3.fromValues(imageOrientationPatient[0], imageOrientationPatient[1], imageOrientationPatient[2]);
33
+ const colOrientation = vec3.fromValues(imageOrientationPatient[3], imageOrientationPatient[4], imageOrientationPatient[5]);
34
+ const normalVector = vec3.cross(vec3.create(), rowOrientation, colOrientation);
35
+ const position = vec3.scaleAndAdd(vec3.create(), imagePositionPatient, normalVector, SpacingBetweenSlices * (frameNumber - 1));
36
+ detectorDerivedImagePositionPatient = [
37
+ position[0],
38
+ position[1],
39
+ position[2],
40
+ ];
41
+ }
42
+ }
43
+ if (!instance._parentInstance) {
44
+ Object.defineProperty(instance, '_parentInstance', {
45
+ value: { ...instance },
46
+ });
47
+ }
48
+ const sharedInstance = createCombinedValue(instance._parentInstance, SharedFunctionalGroupsSequence?.[0], '_shared');
49
+ const newInstance = createCombinedValue(sharedInstance, PerFrameFunctionalGroupsSequence?.[frameNumber - 1], frameNumber);
50
+ if (detectorDerivedImagePositionPatient) {
51
+ newInstance.ImagePositionPatient = detectorDerivedImagePositionPatient;
52
+ }
53
+ else if (!newInstance.ImagePositionPatient && rootImagePositionPatient) {
54
+ newInstance.ImagePositionPatient = rootImagePositionPatient;
55
+ }
56
+ else if (!newInstance.ImagePositionPatient) {
57
+ newInstance.ImagePositionPatient = [0, 0, frameNumber];
58
+ }
59
+ Object.defineProperty(newInstance, 'frameNumber', {
60
+ value: frameNumber,
61
+ writable: true,
62
+ enumerable: true,
63
+ configurable: true,
64
+ });
65
+ return newInstance;
66
+ }
67
+ if (instance.GridFrameOffsetVector) {
68
+ if (!instance._parentInstance) {
69
+ Object.defineProperty(instance, '_parentInstance', {
70
+ value: { ...instance },
71
+ });
72
+ }
73
+ const sharedInstance = createCombinedValue(instance._parentInstance, SharedFunctionalGroupsSequence?.[0], '_shared');
74
+ const newInstance = createCombinedValue(sharedInstance, PerFrameFunctionalGroupsSequence?.[frameNumber - 1], frameNumber);
75
+ const origin = newInstance.ImagePositionPatient?.map(Number);
76
+ const orientation = newInstance.ImageOrientationPatient?.map(Number);
77
+ const offsets = instance.GridFrameOffsetVector;
78
+ const firstOffset = Number(offsets[0]);
79
+ const offset = Number(offsets[frameNumber - 1]);
80
+ if (origin && orientation && !Number.isNaN(offset)) {
81
+ const isIdentityAxialOrientation = isEqual(orientation[0], 1) &&
82
+ isEqual(orientation[1], 0) &&
83
+ isEqual(orientation[2], 0) &&
84
+ isEqual(orientation[3], 0) &&
85
+ isEqual(orientation[4], 1) &&
86
+ isEqual(orientation[5], 0);
87
+ const isRelativeOffsetForm = isEqual(firstOffset, 0);
88
+ const isAbsolutePatientZForm = isIdentityAxialOrientation && isEqual(firstOffset, origin[2]);
89
+ if (isAbsolutePatientZForm) {
90
+ newInstance.ImagePositionPatient = [origin[0], origin[1], offset];
91
+ }
92
+ else if (isRelativeOffsetForm) {
93
+ const row = vec3.fromValues(orientation[0], orientation[1], orientation[2]);
94
+ const col = vec3.fromValues(orientation[3], orientation[4], orientation[5]);
95
+ const normal = vec3.cross(vec3.create(), row, col);
96
+ const position = vec3.scaleAndAdd(vec3.create(), origin, normal, offset);
97
+ newInstance.ImagePositionPatient = [
98
+ position[0],
99
+ position[1],
100
+ position[2],
101
+ ];
102
+ }
103
+ }
104
+ Object.defineProperty(newInstance, 'frameNumber', {
105
+ value: frameNumber,
106
+ writable: true,
107
+ enumerable: true,
108
+ configurable: true,
109
+ });
110
+ return newInstance;
111
+ }
112
+ return instance;
113
+ };
114
+ export function createCombinedValue(parent, functionalGroups, key) {
115
+ if (parent[key]) {
116
+ return parent[key];
117
+ }
118
+ const newInstance = Object.create(parent);
119
+ Object.defineProperty(parent, key, {
120
+ value: newInstance,
121
+ writable: false,
122
+ enumerable: false,
123
+ });
124
+ if (!functionalGroups) {
125
+ return newInstance;
126
+ }
127
+ const shared = functionalGroups
128
+ ? Object.values(functionalGroups)
129
+ .filter(Boolean)
130
+ .map((it) => it[0])
131
+ .filter((it) => typeof it === 'object')
132
+ : [];
133
+ [...shared].forEach((item) => {
134
+ if (item.SOPInstanceUID) {
135
+ return;
136
+ }
137
+ Object.entries(item).forEach(([key, value]) => {
138
+ newInstance[key] = value;
139
+ });
140
+ });
141
+ return newInstance;
142
+ }
143
+ export const combineFrameProvider = (next, query, instance, options) => {
144
+ if (!instance) {
145
+ return next(query, instance, options);
146
+ }
147
+ if (!instance.NumberOfFrames) {
148
+ return instance;
149
+ }
150
+ const uriModule = getMetaData(MetadataModules.URI_MODULE, query, options?.frameModule);
151
+ const { frameNumber = 1 } = uriModule || {};
152
+ const combined = combineFrameInstance(frameNumber, instance);
153
+ return combined;
154
+ };
155
+ export function registerCombineFrameProvider() {
156
+ addTypedProvider(MetadataModules.INSTANCE, combineFrameProvider);
157
+ }
158
+ export default combineFrameInstance;
@@ -0,0 +1 @@
1
+ export declare function registerCompressedFrameDataProvider(): void;
@@ -0,0 +1,133 @@
1
+ import { MetadataModules } from '../../enums';
2
+ import { addTypedProvider } from '../../metaData';
3
+ const PIXEL_DATA_KEYS = [
4
+ 'PixelData',
5
+ 'FramePixelData',
6
+ 'FloatPixelData',
7
+ '7FE00010',
8
+ '7fe00010',
9
+ '7FE00008',
10
+ '7fe00008',
11
+ ];
12
+ const PARAMAP_PIXEL_DATA_KEYS = ['FloatPixelData', '7FE00008', '7fe00008'];
13
+ function getPixelDataFromNatural(natural) {
14
+ for (const key of PIXEL_DATA_KEYS) {
15
+ const val = natural[key];
16
+ if (val !== undefined &&
17
+ val !== null &&
18
+ Array.isArray(val) &&
19
+ val.length > 0) {
20
+ return val;
21
+ }
22
+ }
23
+ return undefined;
24
+ }
25
+ function getPixelDataKeyFromNatural(natural) {
26
+ for (const key of PIXEL_DATA_KEYS) {
27
+ const val = natural[key];
28
+ if (val !== undefined &&
29
+ val !== null &&
30
+ Array.isArray(val) &&
31
+ val.length > 0) {
32
+ return key;
33
+ }
34
+ }
35
+ return undefined;
36
+ }
37
+ function isParamapType(natural) {
38
+ const key = getPixelDataKeyFromNatural(natural);
39
+ return key !== undefined && PARAMAP_PIXEL_DATA_KEYS.includes(key);
40
+ }
41
+ function asView(buf) {
42
+ if (buf instanceof ArrayBuffer) {
43
+ return new Uint8Array(buf);
44
+ }
45
+ return buf;
46
+ }
47
+ function byteLength(buf) {
48
+ if (buf instanceof ArrayBuffer) {
49
+ return buf.byteLength;
50
+ }
51
+ return buf.byteLength;
52
+ }
53
+ function getFramePixelData(pixelDataTag, frameIndex) {
54
+ const frame = pixelDataTag[frameIndex];
55
+ if (frame === undefined || frame === null) {
56
+ return undefined;
57
+ }
58
+ if (Array.isArray(frame)) {
59
+ return frame.map(asView);
60
+ }
61
+ return asView(frame);
62
+ }
63
+ function getFramePixelDataFromSingleBuffer(pixelDataTag, frameIndex, numberOfFrames, natural) {
64
+ if (pixelDataTag.length !== 1 || !isParamapType(natural)) {
65
+ return undefined;
66
+ }
67
+ const buf = pixelDataTag[0];
68
+ if (buf === undefined || buf === null) {
69
+ return undefined;
70
+ }
71
+ const view = asView(buf);
72
+ const totalLength = byteLength(buf);
73
+ if (numberOfFrames <= 0 || totalLength % numberOfFrames !== 0) {
74
+ return undefined;
75
+ }
76
+ const frameSize = totalLength / numberOfFrames;
77
+ const offset = frameIndex * frameSize;
78
+ if (offset + frameSize > totalLength) {
79
+ return undefined;
80
+ }
81
+ console.warn('[compressedFrameData] Splitting single-buffer pixel data by numberOfFrames for paramap-type image; frameIndex=', frameIndex, ', numberOfFrames=', numberOfFrames, ', frameSize=', frameSize);
82
+ const u8 = view instanceof Uint8Array
83
+ ? view
84
+ : new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
85
+ return [u8.subarray(offset, offset + frameSize)];
86
+ }
87
+ function compressedFrameDataFromNatural(natural, frameIndex) {
88
+ if (!natural) {
89
+ return;
90
+ }
91
+ const pixelDataTag = getPixelDataFromNatural(natural);
92
+ if (!pixelDataTag) {
93
+ return;
94
+ }
95
+ const { TransferSyntaxUID: transferSyntaxUid } = natural;
96
+ if (!transferSyntaxUid) {
97
+ return;
98
+ }
99
+ const frameOfInterest = frameIndex ?? 0;
100
+ const frameNumber = frameOfInterest + 1;
101
+ const numberOfFrames = natural.NumberOfFrames != null ? Number(natural.NumberOfFrames) : 1;
102
+ let pixelData;
103
+ if (pixelDataTag.length === numberOfFrames) {
104
+ pixelData = getFramePixelData(pixelDataTag, frameOfInterest);
105
+ }
106
+ else {
107
+ pixelData = getFramePixelDataFromSingleBuffer(pixelDataTag, frameOfInterest, numberOfFrames, natural);
108
+ if (pixelData === undefined) {
109
+ pixelData = getFramePixelData(pixelDataTag, frameOfInterest);
110
+ }
111
+ }
112
+ if (pixelData === undefined) {
113
+ return;
114
+ }
115
+ return {
116
+ transferSyntaxUid,
117
+ frameOfInterest,
118
+ frameNumber,
119
+ pixelData,
120
+ };
121
+ }
122
+ const COMPRESSED_FRAME_DATA_TYPE = MetadataModules.COMPRESSED_FRAME_DATA;
123
+ const compressedFrameDataProvider = (next, query, natural, options) => {
124
+ const frameIndex = options?.frameIndex ?? 0;
125
+ const value = compressedFrameDataFromNatural(natural, frameIndex);
126
+ if (value) {
127
+ return value;
128
+ }
129
+ return next(query, natural, options);
130
+ };
131
+ export function registerCompressedFrameDataProvider() {
132
+ addTypedProvider(COMPRESSED_FRAME_DATA_TYPE, compressedFrameDataProvider);
133
+ }
@@ -0,0 +1,7 @@
1
+ export declare function dataLookup(dataType: string): (next: any, query: any, data: any, options: any) => any;
2
+ export declare const instanceLookup: (next: any, query: any, data: any, options: any) => any;
3
+ export declare const naturalLookup: (next: any, query: any, data: any, options: any) => any;
4
+ export declare const DATA_PRIORITY: {
5
+ priority: number;
6
+ };
7
+ export declare function registerDataLookup(): void;
@@ -0,0 +1,18 @@
1
+ import { MetadataModules } from '../../enums';
2
+ import { addTypedProvider, metadataModuleProvider } from '../../metaData';
3
+ export function dataLookup(dataType) {
4
+ return (next, query, data, options) => {
5
+ data ||= metadataModuleProvider(dataType, query, options?.[dataType]);
6
+ return next(query, data, options);
7
+ };
8
+ }
9
+ export const instanceLookup = dataLookup(MetadataModules.INSTANCE);
10
+ export const naturalLookup = dataLookup(MetadataModules.NATURALIZED);
11
+ export const DATA_PRIORITY = { priority: 5000 };
12
+ export function registerDataLookup() {
13
+ addTypedProvider(MetadataModules.INSTANCE, dataLookup(MetadataModules.NATURALIZED), DATA_PRIORITY);
14
+ addTypedProvider(MetadataModules.IMAGE_PLANE, instanceLookup, DATA_PRIORITY);
15
+ addTypedProvider(MetadataModules.CALIBRATION, instanceLookup, DATA_PRIORITY);
16
+ addTypedProvider(MetadataModules.COMPRESSED_FRAME_DATA, naturalLookup, DATA_PRIORITY);
17
+ addTypedProvider(MetadataModules.SCALING, naturalLookup, DATA_PRIORITY);
18
+ }
@@ -0,0 +1 @@
1
+ export declare function dicomSplit(value: any): any;
@@ -0,0 +1,5 @@
1
+ export function dicomSplit(value) {
2
+ return ((Array.isArray(value) && value) ||
3
+ (typeof value === 'string' && value.split('\\')) ||
4
+ value);
5
+ }
@@ -0,0 +1,18 @@
1
+ export interface EcgModuleFull {
2
+ numberOfWaveformChannels: number;
3
+ numberOfWaveformSamples: number;
4
+ samplingFrequency: number;
5
+ waveformBitsAllocated: number;
6
+ waveformSampleInterpretation: string;
7
+ multiplexGroupLabel: string;
8
+ channelDefinitionSequence: Array<{
9
+ channelSourceSequence?: {
10
+ codeMeaning?: string;
11
+ };
12
+ }>;
13
+ waveformData: {
14
+ retrieveBulkData: () => Promise<Int16Array[]>;
15
+ };
16
+ }
17
+ export declare function buildEcgModuleFromInstance(instance: Record<string, unknown>, imageId?: string): EcgModuleFull | null;
18
+ export declare function registerEcgFromInstanceProvider(): void;