@cornerstonejs/adapters 3.7.0 → 3.7.1

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.
@@ -1,9 +1,11 @@
1
- import { imageLoader } from '@cornerstonejs/core';
1
+ import { triggerEvent, eventTarget, imageLoader } from '@cornerstonejs/core';
2
+ import { utilities as utilities$1 } from '@cornerstonejs/tools';
2
3
  import { utilities, data, normalizers } from 'dcmjs';
3
4
  import ndarray from 'ndarray';
4
5
  import checkOrientation from '../../helpers/checkOrientation.js';
5
6
  import { getValidOrientations, getSegmentMetadata, unpackPixelData, calculateCentroid, readFromUnpackedChunks, alignPixelDataWithSourceData, getSegmentIndex, findReferenceSourceImageId } from '../../Cornerstone/Segmentation_4X.js';
6
7
  import { compactMergeSegmentDataWithoutInformationLoss } from './compactMergeSegData.js';
8
+ import Events from '../../enums/Events.js';
7
9
 
8
10
  const {
9
11
  DicomMessage,
@@ -156,6 +158,11 @@ async function createLabelmapsFromBufferInternal(referencedImageIds, arrayBuffer
156
158
  overlappingSegments: hasOverlappingSegments
157
159
  };
158
160
  }
161
+ const throttledTriggerLoadProgressEvent = utilities$1.throttle(percentComplete => {
162
+ triggerEvent(eventTarget, Events.SEGMENTATION_LOAD_PROGRESS, {
163
+ percentComplete
164
+ });
165
+ }, 200);
159
166
  function insertPixelDataPlanar(_ref4) {
160
167
  let {
161
168
  segmentsOnFrame,
@@ -181,75 +188,86 @@ function insertPixelDataPlanar(_ref4) {
181
188
  const groupsLen = PerFrameFunctionalGroupsSequence.length;
182
189
  let overlapping = false;
183
190
  return new Promise(resolve => {
184
- for (let i = 0; i < groupsLen; ++i) {
185
- const PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[i];
186
- const ImageOrientationPatientI = sharedImageOrientationPatient || PerFrameFunctionalGroups.PlaneOrientationSequence.ImageOrientationPatient;
187
- const view = readFromUnpackedChunks(pixelDataChunks, i * sliceLength, sliceLength);
188
- const pixelDataI2D = ndarray(view, [Rows, Columns]);
189
- const alignedPixelDataI = alignPixelDataWithSourceData(pixelDataI2D, ImageOrientationPatientI, validOrientations, tolerance);
190
- if (!alignedPixelDataI) {
191
- throw new Error("Individual SEG frames are out of plane with respect to the first SEG frame. " + "This is not yet supported. Aborting segmentation loading.");
192
- }
193
- const segmentIndex = getSegmentIndex(multiframe, i);
194
- if (segmentIndex === undefined) {
195
- throw new Error("Could not retrieve the segment index. Aborting segmentation loading.");
196
- }
197
- if (!segmentsPixelIndices.has(segmentIndex)) {
198
- segmentsPixelIndices.set(segmentIndex, {});
199
- }
200
- const imageId = findReferenceSourceImageId(multiframe, i, referencedImageIds, metadataProvider, tolerance, sopUIDImageIdIndexMap);
201
- if (!imageId) {
202
- console.warn("Image not present in stack, can't import frame : " + i + ".");
203
- continue;
204
- }
205
- const sourceImageMetadata = imageIdMaps.metadata[imageId];
206
- if (Rows !== sourceImageMetadata.Rows || Columns !== sourceImageMetadata.Columns) {
207
- throw new Error("Individual SEG frames have different geometry dimensions (Rows and Columns) " + "respect to the source image reference frame. This is not yet supported. " + "Aborting segmentation loading. ");
208
- }
209
- const imageIdIndex = imageIdMaps.indices[imageId];
210
- const labelmapImage = labelMapImages[imageIdIndex];
211
- const labelmap2DView = labelmapImage.getPixelData();
212
- const data = alignedPixelDataI.data;
213
- const indexCache = [];
214
- for (let j = 0, len = alignedPixelDataI.data.length; j < len; ++j) {
215
- if (data[j]) {
216
- for (let x = j; x < len; ++x) {
217
- if (data[x]) {
218
- if (!overlapping && labelmap2DView[x] !== 0) {
219
- overlapping = true;
220
- return resolve(insertOverlappingPixelDataPlanar({
221
- segmentsOnFrame,
222
- labelMapImages,
223
- pixelDataChunks,
224
- multiframe,
225
- referencedImageIds,
226
- validOrientations,
227
- metadataProvider,
228
- tolerance,
229
- segmentsPixelIndices,
230
- sopUIDImageIdIndexMap,
231
- imageIdMaps
232
- }));
191
+ const percentImagesPerChunk = 0.1;
192
+ const imagesPerChunk = Math.ceil(groupsLen * percentImagesPerChunk);
193
+ const processChunk = firstIndex => {
194
+ for (let i = firstIndex; i < firstIndex + imagesPerChunk && i < groupsLen; i++) {
195
+ const PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[i];
196
+ const ImageOrientationPatientI = sharedImageOrientationPatient || PerFrameFunctionalGroups.PlaneOrientationSequence.ImageOrientationPatient;
197
+ const view = readFromUnpackedChunks(pixelDataChunks, i * sliceLength, sliceLength);
198
+ const pixelDataI2D = ndarray(view, [Rows, Columns]);
199
+ const alignedPixelDataI = alignPixelDataWithSourceData(pixelDataI2D, ImageOrientationPatientI, validOrientations, tolerance);
200
+ if (!alignedPixelDataI) {
201
+ throw new Error("Individual SEG frames are out of plane with respect to the first SEG frame. " + "This is not yet supported. Aborting segmentation loading.");
202
+ }
203
+ const segmentIndex = getSegmentIndex(multiframe, i);
204
+ if (segmentIndex === undefined) {
205
+ throw new Error("Could not retrieve the segment index. Aborting segmentation loading.");
206
+ }
207
+ if (!segmentsPixelIndices.has(segmentIndex)) {
208
+ segmentsPixelIndices.set(segmentIndex, {});
209
+ }
210
+ const imageId = findReferenceSourceImageId(multiframe, i, referencedImageIds, metadataProvider, tolerance, sopUIDImageIdIndexMap);
211
+ if (!imageId) {
212
+ console.warn("Image not present in stack, can't import frame : " + i + ".");
213
+ return;
214
+ }
215
+ const sourceImageMetadata = imageIdMaps.metadata[imageId];
216
+ if (Rows !== sourceImageMetadata.Rows || Columns !== sourceImageMetadata.Columns) {
217
+ throw new Error("Individual SEG frames have different geometry dimensions (Rows and Columns) " + "respect to the source image reference frame. This is not yet supported. " + "Aborting segmentation loading. ");
218
+ }
219
+ const imageIdIndex = imageIdMaps.indices[imageId];
220
+ const labelmapImage = labelMapImages[imageIdIndex];
221
+ const labelmap2DView = labelmapImage.getPixelData();
222
+ const data = alignedPixelDataI.data;
223
+ const indexCache = [];
224
+ for (let k = 0, len = alignedPixelDataI.data.length; k < len; ++k) {
225
+ if (data[k]) {
226
+ for (let x = k; x < len; ++x) {
227
+ if (data[x]) {
228
+ if (!overlapping && labelmap2DView[x] !== 0) {
229
+ overlapping = true;
230
+ return resolve(insertOverlappingPixelDataPlanar({
231
+ segmentsOnFrame,
232
+ labelMapImages,
233
+ pixelDataChunks,
234
+ multiframe,
235
+ referencedImageIds,
236
+ validOrientations,
237
+ metadataProvider,
238
+ tolerance,
239
+ segmentsPixelIndices,
240
+ sopUIDImageIdIndexMap,
241
+ imageIdMaps
242
+ }));
243
+ }
244
+ labelmap2DView[x] = segmentIndex;
245
+ indexCache.push(x);
233
246
  }
234
- labelmap2DView[x] = segmentIndex;
235
- indexCache.push(x);
236
247
  }
248
+ if (!segmentsOnFrame[imageIdIndex]) {
249
+ segmentsOnFrame[imageIdIndex] = [];
250
+ }
251
+ segmentsOnFrame[imageIdIndex].push(segmentIndex);
252
+ break;
237
253
  }
238
- if (!segmentsOnFrame[imageIdIndex]) {
239
- segmentsOnFrame[imageIdIndex] = [];
240
- }
241
- segmentsOnFrame[imageIdIndex].push(segmentIndex);
242
- break;
243
254
  }
255
+ const segmentIndexObject = segmentsPixelIndices.get(segmentIndex);
256
+ segmentIndexObject[imageIdIndex] = indexCache;
257
+ segmentsPixelIndices.set(segmentIndex, segmentIndexObject);
244
258
  }
245
- const segmentIndexObject = segmentsPixelIndices.get(segmentIndex);
246
- segmentIndexObject[imageIdIndex] = indexCache;
247
- segmentsPixelIndices.set(segmentIndex, segmentIndexObject);
248
- }
249
- resolve({
250
- hasOverlappingSegments: overlapping,
251
- arrayOfLabelMapImages: [labelMapImages]
252
- });
259
+ const percentComplete = Math.round(firstIndex / groupsLen * 100);
260
+ throttledTriggerLoadProgressEvent(percentComplete);
261
+ if (firstIndex < groupsLen) {
262
+ setTimeout(() => processChunk(firstIndex + imagesPerChunk), 0);
263
+ } else {
264
+ resolve({
265
+ hasOverlappingSegments: false,
266
+ arrayOfLabelMapImages: [labelMapImages]
267
+ });
268
+ }
269
+ };
270
+ processChunk(0);
253
271
  });
254
272
  }
255
273
  const getAlignedPixelData = _ref5 => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/adapters",
3
- "version": "3.7.0",
3
+ "version": "3.7.1",
4
4
  "description": "Adapters for Cornerstone3D to/from formats including DICOM SR and others",
5
5
  "module": "./dist/esm/index.js",
6
6
  "types": "./dist/esm/index.d.ts",
@@ -84,8 +84,8 @@
84
84
  "ndarray": "^1.0.19"
85
85
  },
86
86
  "peerDependencies": {
87
- "@cornerstonejs/core": "^3.7.0",
88
- "@cornerstonejs/tools": "^3.7.0"
87
+ "@cornerstonejs/core": "^3.7.1",
88
+ "@cornerstonejs/tools": "^3.7.1"
89
89
  },
90
- "gitHead": "177fce2dd8c2278d3c8473f15df795e757d40b7e"
90
+ "gitHead": "a4fe414ad0c938b9f842127dea4b0d12e334ac25"
91
91
  }