larvitar 2.0.5 → 2.0.7

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 (77) hide show
  1. package/README.md +2 -2
  2. package/dist/imaging/imageRendering.d.ts +1 -71
  3. package/dist/imaging/imageStore.d.ts +5 -0
  4. package/dist/imaging/loaders/commonLoader.d.ts +4 -4
  5. package/dist/imaging/loaders/nrrdLoader.d.ts +1 -51
  6. package/dist/larvitar.js +13 -1
  7. package/dist/larvitar.js.map +1 -1
  8. package/imaging/tools/types.d.ts +19 -19
  9. package/imaging/types.d.ts +110 -2
  10. package/package.json +7 -2
  11. package/.github/workflows/build-docs.yml +0 -59
  12. package/.github/workflows/codeql-analysis.yml +0 -71
  13. package/.github/workflows/deploy.yml +0 -37
  14. package/.vscode/settings.json +0 -4
  15. package/CODE_OF_CONDUCT.md +0 -76
  16. package/MIGRATION.md +0 -25
  17. package/bundler/webpack.common.js +0 -27
  18. package/bundler/webpack.dev.js +0 -23
  19. package/bundler/webpack.prod.js +0 -19
  20. package/decs.d.ts +0 -12
  21. package/dist/imaging/MetaDataReadable.d.ts +0 -41
  22. package/dist/imaging/MetaDataTypes.d.ts +0 -3489
  23. package/imaging/dataDictionary.json +0 -21866
  24. package/imaging/imageAnonymization.ts +0 -135
  25. package/imaging/imageColormaps.ts +0 -217
  26. package/imaging/imageContours.ts +0 -196
  27. package/imaging/imageIo.ts +0 -251
  28. package/imaging/imageLayers.ts +0 -121
  29. package/imaging/imageLoading.ts +0 -299
  30. package/imaging/imageParsing.ts +0 -444
  31. package/imaging/imagePresets.ts +0 -156
  32. package/imaging/imageRendering.ts +0 -1091
  33. package/imaging/imageReslice.ts +0 -87
  34. package/imaging/imageStore.ts +0 -487
  35. package/imaging/imageTags.ts +0 -609
  36. package/imaging/imageTools.js +0 -708
  37. package/imaging/imageUtils.ts +0 -1079
  38. package/imaging/loaders/commonLoader.ts +0 -275
  39. package/imaging/loaders/dicomLoader.ts +0 -66
  40. package/imaging/loaders/fileLoader.ts +0 -71
  41. package/imaging/loaders/multiframeLoader.ts +0 -435
  42. package/imaging/loaders/nrrdLoader.ts +0 -630
  43. package/imaging/loaders/resliceLoader.ts +0 -205
  44. package/imaging/monitors/memory.ts +0 -151
  45. package/imaging/monitors/performance.ts +0 -34
  46. package/imaging/parsers/ecg.ts +0 -54
  47. package/imaging/parsers/nrrd.js +0 -485
  48. package/imaging/tools/custom/4dSliceScrollTool.js +0 -146
  49. package/imaging/tools/custom/BorderMagnifyTool.js +0 -99
  50. package/imaging/tools/custom/contourTool.js +0 -1884
  51. package/imaging/tools/custom/diameterTool.js +0 -141
  52. package/imaging/tools/custom/editMaskTool.js +0 -141
  53. package/imaging/tools/custom/ellipticalRoiOverlayTool.js +0 -534
  54. package/imaging/tools/custom/polygonSegmentationMixin.js +0 -245
  55. package/imaging/tools/custom/polylineScissorsTool.js +0 -59
  56. package/imaging/tools/custom/rectangleRoiOverlayTool.js +0 -564
  57. package/imaging/tools/custom/seedTool.js +0 -342
  58. package/imaging/tools/custom/setLabelMap3D.ts +0 -242
  59. package/imaging/tools/custom/thresholdsBrushTool.js +0 -161
  60. package/imaging/tools/default.ts +0 -594
  61. package/imaging/tools/interaction.ts +0 -266
  62. package/imaging/tools/io.ts +0 -229
  63. package/imaging/tools/main.ts +0 -427
  64. package/imaging/tools/segmentation.ts +0 -532
  65. package/imaging/tools/segmentations.md +0 -38
  66. package/imaging/tools/state.ts +0 -74
  67. package/imaging/tools/strategies/eraseFreehand.js +0 -76
  68. package/imaging/tools/strategies/fillFreehand.js +0 -79
  69. package/imaging/tools/strategies/index.js +0 -2
  70. package/imaging/waveforms/ecg.ts +0 -191
  71. package/index.ts +0 -431
  72. package/jsdoc.json +0 -52
  73. package/rollup.config.js +0 -51
  74. package/template/.gitkeep +0 -0
  75. package/tsconfig.json +0 -102
  76. /package/imaging/{MetaDataReadable.ts → MetaDataReadable.d.ts} +0 -0
  77. /package/imaging/{MetaDataTypes.ts → MetaDataTypes.d.ts} +0 -0
@@ -1,251 +0,0 @@
1
- /** @module imaging/imageIo
2
- * @desc This file provides I/O functionalities on NRRD files and DICOM images
3
- */
4
-
5
- // external libraries
6
- import cornerstone from "cornerstone-core";
7
- import { forEach, find } from "lodash";
8
-
9
- // internal libraries
10
- import {
11
- getMeanValue,
12
- getDistanceBetweenSlices,
13
- getTypedArrayFromDataType
14
- } from "./imageUtils";
15
- import store from "./imageStore";
16
- import { parse } from "./parsers/nrrd";
17
- import { checkMemoryAllocation } from "./monitors/memory";
18
- import { Series, Header, Volume, TypedArray } from "./types";
19
-
20
- /*
21
- * This module provides the following functions to be exported:
22
- * buildHeader(series)
23
- * getCachedPixelData(imageId)
24
- * buildData(series)
25
- * importNRRDImage(bufferArray)
26
- */
27
-
28
- /**
29
- * Build the image header from slices' metadata
30
- * @function buildHeader
31
- * @param {Object} series - Cornerstone series object
32
- * @returns {Object} header: image metadata
33
- */
34
- export const buildHeader = function (series: Series) {
35
- let header: Partial<Header> = {};
36
-
37
- forEach(series.imageIds, function (imageId: string) {
38
- header[imageId] = series.instances[imageId].metadata;
39
- });
40
-
41
- let volume: Partial<Volume> = {};
42
-
43
- volume.imageIds = series.imageIds;
44
- volume.seriesId = series.instances[series.imageIds[0]].metadata.seriesUID;
45
- volume.rows =
46
- series.instances[series.imageIds[0]].metadata.rows ||
47
- series.instances[series.imageIds[0]].metadata.x00280010;
48
- volume.cols =
49
- series.instances[series.imageIds[0]].metadata.cols ||
50
- series.instances[series.imageIds[0]].metadata.x00280011;
51
- volume.slope = series.instances[series.imageIds[0]].metadata.slope as number;
52
- volume.repr = series.instances[series.imageIds[0]].metadata.repr as string;
53
- volume.intercept = series.instances[series.imageIds[0]].metadata
54
- .intercept as number;
55
- volume.imagePosition = series.instances[series.imageIds[0]].metadata
56
- .imagePosition as [number, number];
57
- volume.numberOfSlices = series.imageIds.length;
58
-
59
- // @ts-ignore
60
- volume.imageOrientation = getMeanValue(
61
- series,
62
- "imageOrientation",
63
- true
64
- ) as number[];
65
-
66
- // @ts-ignore
67
- volume.pixelSpacing = getMeanValue(series, "pixelSpacing", true) as [
68
- number,
69
- number
70
- ];
71
- // volume.maxPixelValue = getMeanValue(series, "maxPixelValue", false);
72
- // volume.minPixelValue = getMeanValue(series, "minPixelValue", false);
73
- volume.sliceThickness = getDistanceBetweenSlices(series, 0, 1);
74
-
75
- header.volume = volume as Volume;
76
-
77
- return header as Header;
78
- };
79
-
80
- /**
81
- * Get cached pixel data
82
- * @function getCachedPixelData
83
- * @param {String} imageId - ImageId of the cached image
84
- * @returns {Promise} A promise which will resolve to a pixel data array or fail if an error occurs
85
- */
86
-
87
- export const getCachedPixelData = function (imageId: string) {
88
- let cachedImage = find(cornerstone.imageCache.cachedImages, [
89
- "imageId",
90
- imageId
91
- ]);
92
- let promise = new Promise<number[]>((resolve, reject) => {
93
- if (cachedImage && cachedImage.image) {
94
- resolve(cachedImage.image.getPixelData());
95
- } else {
96
- cornerstone
97
- .loadImage(imageId)
98
- .then(image => resolve(image.getPixelData()))
99
- .catch(err => reject(err));
100
- }
101
- });
102
- return promise;
103
- };
104
-
105
- /**
106
- * Build the contiguous typed array from slices
107
- * @function buildData
108
- * @param {Object} series - Cornerstone series object
109
- * @param {Bool} useSeriesData - Flag to force using "series" data instead of cached ones
110
- * @returns {Array} Contiguous pixel array
111
- */
112
- export const buildData = function (series: Series, useSeriesData: boolean) {
113
- if (checkMemoryAllocation(series.bytes)) {
114
- let t0 = performance.now();
115
- let repr = series.instances[series.imageIds[0]].metadata.repr;
116
- let rows =
117
- (series.instances[series.imageIds[0]].metadata.rows as number) ||
118
- (series.instances[series.imageIds[0]].metadata.x00280010 as number);
119
- let cols =
120
- (series.instances[series.imageIds[0]].metadata.cols as number) ||
121
- (series.instances[series.imageIds[0]].metadata.x00280011 as number);
122
- let len = rows * cols * series.imageIds.length;
123
-
124
- if (!repr) {
125
- throw new Error("Image representation metadata not found");
126
- }
127
-
128
- let typedArray = getTypedArrayFromDataType(repr as string);
129
-
130
- if (!typedArray) {
131
- throw new Error("Image representation not supported");
132
- }
133
-
134
- let data = new typedArray(len);
135
- let offsetData = 0;
136
-
137
- // use input data or cached data
138
- if (useSeriesData) {
139
- forEach(series.imageIds, function (imageId: string) {
140
- const sliceData = series.instances[imageId].pixelData;
141
- if (sliceData) {
142
- data.set(sliceData, offsetData);
143
- offsetData += sliceData.length;
144
- }
145
- });
146
- let t1 = performance.now();
147
- console.log(`Call to buildData took ${t1 - t0} milliseconds.`);
148
- return data;
149
- } else {
150
- store.addSeriesId(series.seriesUID, series.imageIds);
151
- let image_counter = 0;
152
- forEach(series.imageIds, function (imageId: string) {
153
- getCachedPixelData(imageId).then((sliceData: number[]) => {
154
- data.set(sliceData, offsetData);
155
- offsetData += sliceData.length;
156
- image_counter += 1;
157
- if (image_counter == series.imageIds.length) {
158
- let t1 = performance.now();
159
- console.log(`Call to buildData took ${t1 - t0} milliseconds.`);
160
- return data;
161
- }
162
- });
163
- });
164
- }
165
- } else {
166
- throw new Error("Data has not been builded: not enough memory");
167
- }
168
- };
169
-
170
- /**
171
- * Build the contiguous typed array from slices (async version)
172
- * @function buildDataAsync
173
- * @param {Object} series - Cornerstone series object
174
- * @param {Number} time - Time(s) to wait for garbage collector
175
- * @param {Function} resolve - Promise resolve function
176
- * @param {Function} reject - Promise reject function
177
- */
178
- export const buildDataAsync = function (
179
- series: Series,
180
- time: number,
181
- resolve: (response: TypedArray) => void,
182
- reject: (response: string) => void
183
- ) {
184
- const memoryAllocation = checkMemoryAllocation(series.bytes);
185
-
186
- if (memoryAllocation) {
187
- let t0 = performance.now();
188
- let repr = series.instances[series.imageIds[0]].metadata.repr;
189
- let rows =
190
- (series.instances[series.imageIds[0]].metadata.rows as number) ||
191
- (series.instances[series.imageIds[0]].metadata.x00280010 as number);
192
- let cols =
193
- (series.instances[series.imageIds[0]].metadata.cols as number) ||
194
- (series.instances[series.imageIds[0]].metadata.x00280011 as number);
195
- let len = rows * cols * series.imageIds.length;
196
-
197
- if (!repr) {
198
- throw new Error("Image representation metadata not found");
199
- }
200
-
201
- let typedArray = getTypedArrayFromDataType(repr as string);
202
-
203
- if (!typedArray) {
204
- throw new Error("Image representation not supported");
205
- }
206
-
207
- let data = new typedArray(len);
208
- let offsetData = 0;
209
-
210
- let imageIds = series.imageIds.slice();
211
- store.addSeriesId(series.seriesUID, series.imageIds);
212
-
213
- function runFillPixelData(data: TypedArray) {
214
- let imageId = imageIds.shift();
215
- if (imageId) {
216
- getCachedPixelData(imageId).then(sliceData => {
217
- data.set(sliceData, offsetData);
218
- offsetData += sliceData.length;
219
- // this does the trick: delay next computation to next tick
220
- setTimeout(() => {
221
- runFillPixelData(data);
222
- }, 0);
223
- });
224
- } else {
225
- let t1 = performance.now();
226
- console.log(`Call to buildDataAsync took ${t1 - t0} milliseconds.`);
227
- resolve(data);
228
- }
229
- }
230
- runFillPixelData(data);
231
- } else if (time > 0) {
232
- setTimeout(function () {
233
- time = time - 5;
234
- buildDataAsync(series, time, resolve, reject);
235
- }, 5000);
236
- } else {
237
- reject("Data has not been builded: not enough memory");
238
- }
239
- };
240
-
241
- /**
242
- * Import NRRD image from bufferArray
243
- * @function importNRRDImage
244
- * @param {ArrayBuffer} bufferArray - buffer array from nrrd file
245
- * @returns {Array} Parsed pixel data array
246
- */
247
- export const importNRRDImage = function (bufferArray: ArrayBuffer) {
248
- // get the data
249
- let volume = parse(bufferArray, { headerOnly: false });
250
- return volume;
251
- };
@@ -1,121 +0,0 @@
1
- /** @module imaging/imageLayers
2
- * @desc This file provides functionalities for
3
- * rendering image layers using cornerstone stack
4
- */
5
-
6
- // external libraries
7
- import cornerstone from "cornerstone-core";
8
-
9
- // internal libraries
10
- import { isElement } from "./imageUtils";
11
- import { Series } from "./types";
12
-
13
- /*
14
- * This module provides the following functions to be exported:
15
- * buildLayer(series, tag, options)
16
- * updateLayer(elementId, layerId, options)
17
- * getActiveLayer(elementId)
18
- * setActiveLayer(elementId, layerId)
19
- */
20
-
21
- /**
22
- * Build the image layers object
23
- * @function buildLayers
24
- * @param {Object} series - Cornerstone series object
25
- * @param {String} tag - Tag for the layer
26
- * @param {Object} options - layer options {opacity:float, colormap: str}
27
- * @returns {Object} Cornerstone layer object
28
- */
29
- export const buildLayer = function (
30
- series: Series,
31
- tag: string,
32
- options: { opacity: number; colormap: string }
33
- ) {
34
- let layer = {
35
- imageIds: series.imageIds,
36
- currentImageIdIndex: Math.floor(series.imageIds.length / 2),
37
- options: {
38
- name: tag,
39
- opacity: options?.opacity ? options?.opacity : 1.0,
40
- visible: true,
41
- viewport: {
42
- colormap: options?.colormap ? options?.colormap : "gray"
43
- }
44
- }
45
- };
46
- return layer;
47
- };
48
-
49
- /**
50
- * Change the options of a layer
51
- * @instance
52
- * @function updateLayer
53
- * @param {String} elementId - The html div id used for rendering or its DOM HTMLElement
54
- * @param {string} layer - The layer id
55
- * @param {Object} options - The new layer's options
56
- */
57
- export const updateLayer = function (
58
- elementId: string | HTMLElement,
59
- layerId: string,
60
- options: { opacity: number; colormap: string }
61
- ) {
62
- let element = isElement(elementId)
63
- ? (elementId as HTMLElement)
64
- : document.getElementById(elementId as string);
65
- if (!element) {
66
- console.log("not element");
67
- return;
68
- }
69
- let layer = cornerstone.getLayer(element, layerId);
70
- if (!layer.options) {
71
- layer["options"] = {};
72
- }
73
- if (!layer.viewport) {
74
- layer["viewport"] = {};
75
- }
76
- layer.options.opacity =
77
- options.opacity != null ? options.opacity : layer.options.opacity;
78
- layer.viewport.colormap = options.colormap
79
- ? options.colormap
80
- : layer.viewport.colormap;
81
- cornerstone.updateImage(element);
82
- };
83
-
84
- /**
85
- * Get the active layer
86
- * @instance
87
- * @function getActiveLayer
88
- * @param {String} elementId - The html div id used for rendering or its DOM HTMLElement
89
- * @returns {Object} layer - The active layer object
90
- */
91
- export const getActiveLayer = function (elementId: string | HTMLElement) {
92
- let element = isElement(elementId)
93
- ? (elementId as HTMLElement)
94
- : document.getElementById(elementId as string);
95
- if (!element) {
96
- console.log("not element");
97
- return;
98
- }
99
- return cornerstone.getActiveLayer(element);
100
- };
101
-
102
- /**
103
- * Set the active layer
104
- * @instance
105
- * @function setActiveLayer
106
- * @param {String} elementId - The html div id used for rendering or its DOM HTMLElement
107
- * @param {String} layerId - The id of the layer
108
- */
109
- export const setActiveLayer = function (
110
- elementId: string | HTMLElement,
111
- layerId: string
112
- ) {
113
- let element = isElement(elementId)
114
- ? (elementId as HTMLElement)
115
- : document.getElementById(elementId as string);
116
- if (!element) {
117
- console.log("not element");
118
- return;
119
- }
120
- cornerstone.setActiveLayer(element, layerId);
121
- };
@@ -1,299 +0,0 @@
1
- /** @module imaging/imageLoading
2
- * @desc This file provides functionalities for
3
- * initialize, configure and update DICOMImageLoader
4
- */
5
-
6
- // external libraries
7
- import cornerstone from "cornerstone-core";
8
- import dicomParser from "dicom-parser";
9
- // import cornerstoneDICOMImageLoader from "@cornerstonejs/dicom-image-loader/dist/cornerstoneDICOMImageLoader.bundle.min.js";
10
- import { default as cornerstoneDICOMImageLoader } from "cornerstone-wado-image-loader";
11
- import cornerstoneWebImageLoader from "cornerstone-web-image-loader";
12
- import cornerstoneFileImageLoader from "cornerstone-file-image-loader";
13
- import { forEach } from "lodash";
14
-
15
- // internal libraries
16
- import store from "./imageStore";
17
- import { getSortedStack, getSortedUIDs } from "./imageUtils";
18
- import { loadNrrdImage } from "./loaders/nrrdLoader";
19
- import { loadReslicedImage } from "./loaders/resliceLoader";
20
- import { loadMultiFrameImage } from "./loaders/multiframeLoader";
21
- import { ImageObject, Instance, Series, StagedProtocol } from "./types";
22
- import { getLarvitarManager } from "./loaders/commonLoader";
23
-
24
- /**
25
- * Global standard configuration
26
- * @inner
27
- * @var {Object} globalConfig
28
- * @property {Number} maxWebWorkers - number of maximum web workers
29
- * @property {String} webWorkerPath - path to default DICOM web worker
30
- * @property {} - see https://github.com/cornerstonejs/cornerstoneDICOMImageLoader/blob/master/docs/WebWorkers.md
31
- */
32
-
33
- const MAX_CONCURRENCY = 6;
34
- const globalConfig = {
35
- maxWebWorkers: Math.max(
36
- Math.min(navigator.hardwareConcurrency - 1, MAX_CONCURRENCY),
37
- 1
38
- ),
39
- startWebWorkersOnDemand: true,
40
- taskConfiguration: {
41
- decodeTask: {
42
- loadCodecsOnStartup: true,
43
- initializeCodecsOnStartup: false,
44
- strict: true
45
- }
46
- }
47
- };
48
-
49
- /*
50
- * This module provides the following functions to be exported:
51
- * initializeImageLoader(config)
52
- * initializeWebImageLoader()
53
- * initializeFileImageLoader()
54
- * registerNRRDImageLoader()
55
- * registerResliceLoader()
56
- * updateLoadedStack(seriesData, allSeriesStack)
57
- */
58
-
59
- /**
60
- * Configure DICOMImageLoader
61
- * @instance
62
- * @function initializeImageLoader
63
- * @param {Object} config - Custom config @default globalConfig
64
- */
65
- export const initializeImageLoader = function (config?: typeof globalConfig) {
66
- let imageLoaderConfig = config ? config : globalConfig;
67
- cornerstoneDICOMImageLoader.external.cornerstone = cornerstone;
68
- cornerstoneDICOMImageLoader.external.dicomParser = dicomParser;
69
- cornerstoneDICOMImageLoader.webWorkerManager.initialize(imageLoaderConfig);
70
- };
71
-
72
- /**
73
- * Configure cornerstoneWebImageLoader
74
- * @instance
75
- * @function initializeWebImageLoader
76
- */
77
- export const initializeWebImageLoader = function () {
78
- cornerstoneWebImageLoader.external.cornerstone = cornerstone;
79
- cornerstoneWebImageLoader.configure({
80
- beforeSend: function () {
81
- // add xhr as function arg
82
- // Add custom headers here (e.g. auth tokens)
83
- // xhr.setRequestHeader('x-auth-token', 'my auth token');
84
- }
85
- });
86
- };
87
-
88
- /**
89
- * Configure cornerstoneFileImageLoader
90
- * @instance
91
- * @function initializeFileImageLoader
92
- */
93
- export const initializeFileImageLoader = function () {
94
- cornerstoneFileImageLoader.external.cornerstone = cornerstone;
95
- };
96
-
97
- /**
98
- * Register custom NRRD ImageLoader
99
- * @instance
100
- * @function registerNRRDImageLoader
101
- */
102
- export const registerNRRDImageLoader = function () {
103
- cornerstone.registerImageLoader("nrrdLoader", loadNrrdImage);
104
- };
105
-
106
- /**
107
- * Register custom Reslice ImageLoader
108
- * @instance
109
- * @function registerResliceLoader
110
- */
111
- export const registerResliceLoader = function () {
112
- cornerstone.registerImageLoader("resliceLoader", loadReslicedImage);
113
- };
114
-
115
- /**
116
- * Register custom MultiFrame ImageLoader
117
- * @instance
118
- * @function registerMultiFrameImageLoader
119
- */
120
- export const registerMultiFrameImageLoader = function () {
121
- cornerstone.registerImageLoader("multiFrameLoader", loadMultiFrameImage);
122
- };
123
-
124
- /**
125
- * Update the allSeriesStack object using DICOMImageLoader fileManager
126
- * @instance
127
- * @function updateLoadedStack
128
- * @param {Object} seriesData - Cornerstone series object
129
- * @param {Object} allSeriesStack - Dict containing all series objects
130
- * @param {String} customId - Optional custom id to overwrite seriesUID as default one
131
- * @param {number} sliceIndex - Optional custom index to overwrite slice index as default one
132
- */
133
- export const updateLoadedStack = function (
134
- seriesData: ImageObject,
135
- allSeriesStack: ReturnType<typeof getLarvitarManager>,
136
- customId?: string,
137
- sliceIndex?: number
138
- ) {
139
- let lid = seriesData.metadata.larvitarSeriesInstanceUID;
140
- let sid = seriesData.metadata.seriesUID;
141
- let ssid = seriesData.metadata.studyUID;
142
- let iid = seriesData.metadata.instanceUID as string;
143
- let seriesDescription = seriesData.metadata.seriesDescription;
144
- let numberOfSlices = seriesData.metadata["x00540081"]
145
- ? seriesData.metadata["x00540081"]
146
- : seriesData.metadata["x00201002"];
147
- let numberOfFrames = seriesData.metadata["x00280008"];
148
- let modality = seriesData.metadata["x00080060"];
149
- let isMultiframe =
150
- numberOfFrames && (numberOfFrames as number) > 1 ? true : false;
151
- let numberOfTemporalPositions = seriesData.metadata["x00200105"];
152
- let acquisitionNumberAttribute = seriesData.metadata["x00200012"];
153
- let is4D = seriesData.metadata.is4D;
154
- let waveform = seriesData.metadata.waveform;
155
- let SOPUID = seriesData.metadata["x00080016"];
156
- let isPDF = SOPUID == "1.2.840.10008.5.1.4.1.1.104.1" ? true : false;
157
- let anonymized = seriesData.metadata.anonymized;
158
-
159
- let color = cornerstoneDICOMImageLoader.isColorImage(
160
- seriesData.metadata["x00280004"]
161
- ) as boolean;
162
- let id = customId || lid?.toString();
163
-
164
- if (!id) {
165
- throw new Error("Unique UID is not defined");
166
- }
167
-
168
- // Staged Protocol
169
- // https://dicom.nema.org/dicom/2013/output/chtml/part17/sect_K.5.html
170
- const numberOfStages = seriesData.metadata["x00082124"]; // Number of stages
171
- const numberOfViews = seriesData.metadata["x0008212a"]; // Number of views in stage
172
- const isStagedProtocol = numberOfStages ? true : false;
173
-
174
- // initialize series stack
175
- if (!allSeriesStack[id]) {
176
- let series: Partial<Series> = {
177
- currentImageIdIndex: 0,
178
- imageIds: [], // (ordered)
179
- instanceUIDs: {}, // instanceUID: imageId (ordered)
180
- instances: {},
181
- seriesDescription: seriesDescription as string,
182
- larvitarSeriesInstanceUID: lid as string,
183
- seriesUID: sid as string,
184
- studyUID: ssid as string,
185
- numberOfImages: is4D ? (acquisitionNumberAttribute as number) : 0,
186
- numberOfSlices: numberOfSlices as number,
187
- numberOfFrames: numberOfFrames as number,
188
- numberOfTemporalPositions: numberOfTemporalPositions as number,
189
- isMultiframe: isMultiframe,
190
- waveform: waveform as boolean,
191
- is4D: is4D as boolean,
192
- isPDF: isPDF as boolean,
193
- anonymized: anonymized as boolean,
194
- modality: modality as string,
195
- color: color,
196
- bytes: 0
197
- };
198
- if (isStagedProtocol) {
199
- const stageName = seriesData.metadata["x00082120"];
200
- const stageNumber = seriesData.metadata["x00082122"];
201
- const viewName = seriesData.metadata["x00082127"];
202
- const viewNumber = seriesData.metadata["x00082128"];
203
- const stagedProtocol: StagedProtocol = {
204
- numberOfStages: numberOfStages as number,
205
- numberOfViews: numberOfViews as number,
206
- stageName: stageName ? (stageName as string).trim() : undefined,
207
- stageNumber: stageNumber as number,
208
- viewName: viewName ? (viewName as string).trim() : undefined,
209
- viewNumber: viewNumber as number
210
- };
211
- series.stagedProtocol = stagedProtocol;
212
- }
213
- allSeriesStack[id] = series as Series;
214
- }
215
-
216
- // get instance number from metadata
217
- const instanceNumber = seriesData.metadata["x00200013"];
218
- const defaultMethod = instanceNumber ? "instanceNumber" : "imagePosition";
219
- const sortMethods: Array<"imagePosition" | "contentTime" | "instanceNumber"> =
220
- is4D ? [defaultMethod, "contentTime"] : [defaultMethod];
221
-
222
- // if the parsed file is a new series instance, keep it
223
-
224
- if (isMultiframe) {
225
- allSeriesStack[id].bytes += seriesData.file.size;
226
- allSeriesStack[id].dataSet = seriesData.dataSet;
227
- allSeriesStack[id].metadata = seriesData.metadata;
228
- } else if (isNewInstance(allSeriesStack[id].instances, iid!)) {
229
- // generate an imageId for the file and store it
230
- // in allSeriesStack imageIds array, used by
231
- // DICOMImageLoader to display the stack of images
232
- let imageId = cornerstoneDICOMImageLoader.wadouri.fileManager.add(
233
- seriesData.file
234
- ) as string;
235
-
236
- if (sliceIndex !== undefined) {
237
- allSeriesStack[id].imageIds[sliceIndex] = imageId;
238
- } else {
239
- allSeriesStack[id].imageIds.push(imageId);
240
- }
241
-
242
- if (is4D === false) {
243
- allSeriesStack[id].numberOfImages =
244
- (allSeriesStack[id].numberOfImages || 0) + 1;
245
- }
246
-
247
- allSeriesStack[id].bytes += seriesData.file.size;
248
- // store needed instance tags
249
- allSeriesStack[id].instances[imageId] = {
250
- metadata: seriesData.metadata,
251
- file: seriesData.file,
252
- dataSet: seriesData.dataSet
253
- };
254
-
255
- if (isPDF === false) {
256
- if (sliceIndex === undefined) {
257
- // order images in stack
258
- allSeriesStack[id].imageIds = getSortedStack(
259
- allSeriesStack[id] as Series,
260
- sortMethods,
261
- true
262
- );
263
- // populate the ordered dictionary of instanceUIDs
264
- allSeriesStack[id].instanceUIDs = getSortedUIDs(
265
- allSeriesStack[id] as Series
266
- );
267
- } else {
268
- allSeriesStack[id].instanceUIDs[iid] = imageId;
269
- }
270
- store.addSeriesId(id, allSeriesStack[id].imageIds);
271
- } else {
272
- allSeriesStack[id].instanceUIDs[iid] = imageId;
273
- store.addSeriesId(id, allSeriesStack[id].imageIds);
274
- }
275
- }
276
- };
277
-
278
- /* Internal module functions */
279
-
280
- /**
281
- * Check if the instance is new or not
282
- * @inner
283
- * @function isNewInstance
284
- * @param {Object} instances - instances already loaded
285
- * @param {String} iid - instance uid to check
286
- * @return {Bool} True if is new instance, false if already present
287
- */
288
- let isNewInstance = function (
289
- instances: { [key: string]: Instance },
290
- iid: string
291
- ) {
292
- let isNewInstance = true;
293
- forEach(instances, function (instance: Instance) {
294
- if (instance.metadata.instanceUID === iid) {
295
- isNewInstance = false;
296
- }
297
- });
298
- return isNewInstance;
299
- };