@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
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
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.
|
|
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.
|
|
88
|
-
"@cornerstonejs/tools": "^3.7.
|
|
87
|
+
"@cornerstonejs/core": "^3.7.1",
|
|
88
|
+
"@cornerstonejs/tools": "^3.7.1"
|
|
89
89
|
},
|
|
90
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "a4fe414ad0c938b9f842127dea4b0d12e334ac25"
|
|
91
91
|
}
|