larvitar 2.0.4 → 2.0.6

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 (72) hide show
  1. package/README.md +2 -2
  2. package/dist/larvitar.js +5 -3
  3. package/dist/larvitar.js.map +1 -1
  4. package/package.json +6 -2
  5. package/.github/workflows/build-docs.yml +0 -59
  6. package/.github/workflows/codeql-analysis.yml +0 -71
  7. package/.github/workflows/deploy.yml +0 -37
  8. package/.vscode/settings.json +0 -4
  9. package/CODE_OF_CONDUCT.md +0 -76
  10. package/MIGRATION.md +0 -25
  11. package/bundler/webpack.common.js +0 -27
  12. package/bundler/webpack.dev.js +0 -23
  13. package/bundler/webpack.prod.js +0 -19
  14. package/decs.d.ts +0 -12
  15. package/imaging/MetaDataReadable.ts +0 -42
  16. package/imaging/MetaDataTypes.ts +0 -3491
  17. package/imaging/dataDictionary.json +0 -21866
  18. package/imaging/imageAnonymization.ts +0 -135
  19. package/imaging/imageColormaps.ts +0 -217
  20. package/imaging/imageContours.ts +0 -196
  21. package/imaging/imageIo.ts +0 -251
  22. package/imaging/imageLayers.ts +0 -121
  23. package/imaging/imageLoading.ts +0 -299
  24. package/imaging/imageParsing.ts +0 -444
  25. package/imaging/imagePresets.ts +0 -156
  26. package/imaging/imageRendering.ts +0 -1091
  27. package/imaging/imageReslice.ts +0 -87
  28. package/imaging/imageStore.ts +0 -487
  29. package/imaging/imageTags.ts +0 -609
  30. package/imaging/imageTools.js +0 -708
  31. package/imaging/imageUtils.ts +0 -1079
  32. package/imaging/loaders/commonLoader.ts +0 -275
  33. package/imaging/loaders/dicomLoader.ts +0 -66
  34. package/imaging/loaders/fileLoader.ts +0 -71
  35. package/imaging/loaders/multiframeLoader.ts +0 -435
  36. package/imaging/loaders/nrrdLoader.ts +0 -630
  37. package/imaging/loaders/resliceLoader.ts +0 -205
  38. package/imaging/monitors/memory.ts +0 -151
  39. package/imaging/monitors/performance.ts +0 -34
  40. package/imaging/parsers/ecg.ts +0 -54
  41. package/imaging/parsers/nrrd.js +0 -485
  42. package/imaging/tools/README.md +0 -27
  43. package/imaging/tools/custom/4dSliceScrollTool.js +0 -146
  44. package/imaging/tools/custom/BorderMagnifyTool.js +0 -99
  45. package/imaging/tools/custom/contourTool.js +0 -1884
  46. package/imaging/tools/custom/diameterTool.js +0 -141
  47. package/imaging/tools/custom/editMaskTool.js +0 -141
  48. package/imaging/tools/custom/ellipticalRoiOverlayTool.js +0 -534
  49. package/imaging/tools/custom/polygonSegmentationMixin.js +0 -245
  50. package/imaging/tools/custom/polylineScissorsTool.js +0 -59
  51. package/imaging/tools/custom/rectangleRoiOverlayTool.js +0 -564
  52. package/imaging/tools/custom/seedTool.js +0 -342
  53. package/imaging/tools/custom/setLabelMap3D.ts +0 -242
  54. package/imaging/tools/custom/thresholdsBrushTool.js +0 -161
  55. package/imaging/tools/default.ts +0 -594
  56. package/imaging/tools/interaction.ts +0 -266
  57. package/imaging/tools/io.ts +0 -229
  58. package/imaging/tools/main.ts +0 -424
  59. package/imaging/tools/segmentation.ts +0 -532
  60. package/imaging/tools/segmentations.md +0 -38
  61. package/imaging/tools/state.ts +0 -74
  62. package/imaging/tools/strategies/eraseFreehand.js +0 -76
  63. package/imaging/tools/strategies/fillFreehand.js +0 -79
  64. package/imaging/tools/strategies/index.js +0 -2
  65. package/imaging/tools/types.d.ts +0 -243
  66. package/imaging/types.d.ts +0 -200
  67. package/imaging/waveforms/ecg.ts +0 -191
  68. package/index.ts +0 -431
  69. package/jsdoc.json +0 -52
  70. package/rollup.config.js +0 -51
  71. package/template/.gitkeep +0 -0
  72. package/tsconfig.json +0 -102
@@ -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
- };