@cornerstonejs/core 1.53.0 → 1.54.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.
- package/dist/cjs/RenderingEngine/RenderingEngine.js +5 -0
- package/dist/cjs/RenderingEngine/RenderingEngine.js.map +1 -1
- package/dist/cjs/RenderingEngine/Viewport.d.ts +1 -2
- package/dist/cjs/RenderingEngine/Viewport.js +21 -8
- package/dist/cjs/RenderingEngine/Viewport.js.map +1 -1
- package/dist/cjs/RenderingEngine/VolumeViewport.d.ts +14 -2
- package/dist/cjs/RenderingEngine/VolumeViewport.js +60 -12
- package/dist/cjs/RenderingEngine/VolumeViewport.js.map +1 -1
- package/dist/cjs/RenderingEngine/VolumeViewport3D.d.ts +0 -1
- package/dist/cjs/RenderingEngine/VolumeViewport3D.js +0 -7
- package/dist/cjs/RenderingEngine/VolumeViewport3D.js.map +1 -1
- package/dist/cjs/RenderingEngine/helpers/setDefaultVolumeVOI.js +10 -7
- package/dist/cjs/RenderingEngine/helpers/setDefaultVolumeVOI.js.map +1 -1
- package/dist/cjs/cache/cache.d.ts +2 -0
- package/dist/cjs/cache/cache.js +10 -0
- package/dist/cjs/cache/cache.js.map +1 -1
- package/dist/cjs/cache/classes/ImageVolume.d.ts +1 -0
- package/dist/cjs/cache/classes/ImageVolume.js +25 -3
- package/dist/cjs/cache/classes/ImageVolume.js.map +1 -1
- package/dist/cjs/cache/classes/Surface.d.ts +6 -3
- package/dist/cjs/cache/classes/Surface.js +9 -0
- package/dist/cjs/cache/classes/Surface.js.map +1 -1
- package/dist/cjs/cache/index.d.ts +2 -1
- package/dist/cjs/cache/index.js +3 -1
- package/dist/cjs/cache/index.js.map +1 -1
- package/dist/cjs/constants/backgroundColors.d.ts +4 -0
- package/dist/cjs/constants/backgroundColors.js +7 -0
- package/dist/cjs/constants/backgroundColors.js.map +1 -0
- package/dist/cjs/constants/index.d.ts +2 -1
- package/dist/cjs/constants/index.js +3 -1
- package/dist/cjs/constants/index.js.map +1 -1
- package/dist/cjs/enums/Events.d.ts +2 -1
- package/dist/cjs/enums/Events.js +1 -0
- package/dist/cjs/enums/Events.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/loaders/volumeLoader.d.ts +10 -2
- package/dist/cjs/loaders/volumeLoader.js +49 -29
- package/dist/cjs/loaders/volumeLoader.js.map +1 -1
- package/dist/cjs/requestPool/requestPoolManager.js +1 -1
- package/dist/cjs/requestPool/requestPoolManager.js.map +1 -1
- package/dist/cjs/types/IGeometry.d.ts +2 -2
- package/dist/cjs/types/IImageVolume.d.ts +2 -1
- package/dist/cjs/types/ISurface.d.ts +13 -0
- package/dist/cjs/types/ISurface.js +3 -0
- package/dist/cjs/types/ISurface.js.map +1 -0
- package/dist/cjs/types/index.d.ts +2 -1
- package/dist/cjs/utilities/VoxelManager.d.ts +1 -1
- package/dist/cjs/utilities/VoxelManager.js +3 -0
- package/dist/cjs/utilities/VoxelManager.js.map +1 -1
- package/dist/cjs/utilities/cacheUtils.js +16 -1
- package/dist/cjs/utilities/cacheUtils.js.map +1 -1
- package/dist/cjs/utilities/convertVolumeToStackViewport.js +1 -1
- package/dist/cjs/utilities/convertVolumeToStackViewport.js.map +1 -1
- package/dist/cjs/utilities/generateVolumePropsFromImageIds.js.map +1 -1
- package/dist/cjs/utilities/getViewportImageIds.d.ts +3 -0
- package/dist/cjs/utilities/getViewportImageIds.js +20 -0
- package/dist/cjs/utilities/getViewportImageIds.js.map +1 -0
- package/dist/cjs/utilities/index.d.ts +2 -1
- package/dist/cjs/utilities/index.js +3 -1
- package/dist/cjs/utilities/index.js.map +1 -1
- package/dist/cjs/webWorkerManager/webWorkerManager.d.ts +3 -3
- package/dist/cjs/webWorkerManager/webWorkerManager.js +40 -30
- package/dist/cjs/webWorkerManager/webWorkerManager.js.map +1 -1
- package/dist/esm/RenderingEngine/RenderingEngine.js +5 -0
- package/dist/esm/RenderingEngine/RenderingEngine.js.map +1 -1
- package/dist/esm/RenderingEngine/Viewport.js +21 -8
- package/dist/esm/RenderingEngine/Viewport.js.map +1 -1
- package/dist/esm/RenderingEngine/VolumeViewport.js +61 -13
- package/dist/esm/RenderingEngine/VolumeViewport.js.map +1 -1
- package/dist/esm/RenderingEngine/VolumeViewport3D.js +0 -7
- package/dist/esm/RenderingEngine/VolumeViewport3D.js.map +1 -1
- package/dist/esm/RenderingEngine/helpers/setDefaultVolumeVOI.js +7 -7
- package/dist/esm/RenderingEngine/helpers/setDefaultVolumeVOI.js.map +1 -1
- package/dist/esm/cache/cache.js +10 -0
- package/dist/esm/cache/cache.js.map +1 -1
- package/dist/esm/cache/classes/ImageVolume.js +24 -2
- package/dist/esm/cache/classes/ImageVolume.js.map +1 -1
- package/dist/esm/cache/classes/Surface.js +9 -0
- package/dist/esm/cache/classes/Surface.js.map +1 -1
- package/dist/esm/cache/index.js +2 -1
- package/dist/esm/cache/index.js.map +1 -1
- package/dist/esm/constants/backgroundColors.js +5 -0
- package/dist/esm/constants/backgroundColors.js.map +1 -0
- package/dist/esm/constants/index.js +2 -1
- package/dist/esm/constants/index.js.map +1 -1
- package/dist/esm/enums/Events.js +1 -0
- package/dist/esm/enums/Events.js.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/loaders/volumeLoader.js +45 -28
- package/dist/esm/loaders/volumeLoader.js.map +1 -1
- package/dist/esm/requestPool/requestPoolManager.js +1 -1
- package/dist/esm/requestPool/requestPoolManager.js.map +1 -1
- package/dist/esm/types/ISurface.js +2 -0
- package/dist/esm/types/ISurface.js.map +1 -0
- package/dist/esm/utilities/VoxelManager.js +3 -0
- package/dist/esm/utilities/VoxelManager.js.map +1 -1
- package/dist/esm/utilities/cacheUtils.js +15 -1
- package/dist/esm/utilities/cacheUtils.js.map +1 -1
- package/dist/esm/utilities/convertVolumeToStackViewport.js +1 -1
- package/dist/esm/utilities/convertVolumeToStackViewport.js.map +1 -1
- package/dist/esm/utilities/generateVolumePropsFromImageIds.js.map +1 -1
- package/dist/esm/utilities/getViewportImageIds.js +15 -0
- package/dist/esm/utilities/getViewportImageIds.js.map +1 -0
- package/dist/esm/utilities/index.js +2 -1
- package/dist/esm/utilities/index.js.map +1 -1
- package/dist/esm/webWorkerManager/webWorkerManager.js +40 -30
- package/dist/esm/webWorkerManager/webWorkerManager.js.map +1 -1
- package/dist/types/RenderingEngine/RenderingEngine.d.ts.map +1 -1
- package/dist/types/RenderingEngine/Viewport.d.ts +1 -2
- package/dist/types/RenderingEngine/Viewport.d.ts.map +1 -1
- package/dist/types/RenderingEngine/VolumeViewport.d.ts +14 -2
- package/dist/types/RenderingEngine/VolumeViewport.d.ts.map +1 -1
- package/dist/types/RenderingEngine/VolumeViewport3D.d.ts +0 -1
- package/dist/types/RenderingEngine/VolumeViewport3D.d.ts.map +1 -1
- package/dist/types/RenderingEngine/helpers/setDefaultVolumeVOI.d.ts.map +1 -1
- package/dist/types/cache/cache.d.ts +2 -0
- package/dist/types/cache/cache.d.ts.map +1 -1
- package/dist/types/cache/classes/ImageVolume.d.ts +1 -0
- package/dist/types/cache/classes/ImageVolume.d.ts.map +1 -1
- package/dist/types/cache/classes/Surface.d.ts +6 -3
- package/dist/types/cache/classes/Surface.d.ts.map +1 -1
- package/dist/types/cache/index.d.ts +2 -1
- package/dist/types/cache/index.d.ts.map +1 -1
- package/dist/types/constants/backgroundColors.d.ts +5 -0
- package/dist/types/constants/backgroundColors.d.ts.map +1 -0
- package/dist/types/constants/index.d.ts +2 -1
- package/dist/types/constants/index.d.ts.map +1 -1
- package/dist/types/enums/Events.d.ts +2 -1
- package/dist/types/enums/Events.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/loaders/volumeLoader.d.ts +10 -2
- package/dist/types/loaders/volumeLoader.d.ts.map +1 -1
- package/dist/types/requestPool/requestPoolManager.d.ts.map +1 -1
- package/dist/types/types/IGeometry.d.ts +2 -2
- package/dist/types/types/IGeometry.d.ts.map +1 -1
- package/dist/types/types/IImageVolume.d.ts +2 -1
- package/dist/types/types/IImageVolume.d.ts.map +1 -1
- package/dist/types/types/ISurface.d.ts +14 -0
- package/dist/types/types/ISurface.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +2 -1
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/utilities/VoxelManager.d.ts +1 -1
- package/dist/types/utilities/VoxelManager.d.ts.map +1 -1
- package/dist/types/utilities/generateVolumePropsFromImageIds.d.ts.map +1 -1
- package/dist/types/utilities/getViewportImageIds.d.ts +4 -0
- package/dist/types/utilities/getViewportImageIds.d.ts.map +1 -0
- package/dist/types/utilities/index.d.ts +2 -1
- package/dist/types/utilities/index.d.ts.map +1 -1
- package/dist/types/webWorkerManager/webWorkerManager.d.ts +3 -3
- package/dist/types/webWorkerManager/webWorkerManager.d.ts.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +2 -2
- package/src/RenderingEngine/RenderingEngine.ts +8 -0
- package/src/RenderingEngine/Viewport.ts +35 -10
- package/src/RenderingEngine/VolumeViewport.ts +135 -16
- package/src/RenderingEngine/VolumeViewport3D.ts +0 -8
- package/src/RenderingEngine/helpers/setDefaultVolumeVOI.ts +17 -12
- package/src/cache/cache.ts +25 -0
- package/src/cache/classes/ImageVolume.ts +37 -4
- package/src/cache/classes/Surface.ts +16 -4
- package/src/cache/index.ts +2 -1
- package/src/constants/backgroundColors.ts +5 -0
- package/src/constants/index.ts +2 -0
- package/src/enums/Events.ts +8 -0
- package/src/index.ts +2 -1
- package/src/loaders/volumeLoader.ts +109 -43
- package/src/requestPool/requestPoolManager.ts +7 -1
- package/src/types/IGeometry.ts +2 -2
- package/src/types/IImageVolume.ts +9 -1
- package/src/types/ISurface.ts +14 -0
- package/src/types/index.ts +2 -0
- package/src/utilities/VoxelManager.ts +7 -1
- package/src/utilities/cacheUtils.ts +25 -1
- package/src/utilities/convertVolumeToStackViewport.ts +1 -1
- package/src/utilities/generateVolumePropsFromImageIds.ts +1 -2
- package/src/utilities/getViewportImageIds.ts +22 -0
- package/src/utilities/index.ts +2 -0
- package/src/webWorkerManager/webWorkerManager.js +71 -43
|
@@ -45,12 +45,19 @@ interface DerivedVolumeOptions {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
interface LocalVolumeOptions {
|
|
48
|
-
scalarData: PixelDataTypedArray;
|
|
49
48
|
metadata: Metadata;
|
|
50
49
|
dimensions: Point3;
|
|
51
50
|
spacing: Point3;
|
|
52
51
|
origin: Point3;
|
|
53
52
|
direction: Mat3;
|
|
53
|
+
scalarData?: PixelDataTypedArray;
|
|
54
|
+
imageIds?: Array<string>;
|
|
55
|
+
referencedImageIds?: Array<string>;
|
|
56
|
+
referencedVolumeId?: string;
|
|
57
|
+
targetBuffer?: {
|
|
58
|
+
type: PixelDataTypedArrayString;
|
|
59
|
+
sharedArrayBuffer?: boolean;
|
|
60
|
+
};
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
/**
|
|
@@ -295,32 +302,11 @@ export async function createAndCacheDerivedVolume(
|
|
|
295
302
|
const scalarData = referencedVolume.getScalarData();
|
|
296
303
|
const scalarLength = scalarData.length;
|
|
297
304
|
|
|
298
|
-
const {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const { TypedArrayConstructor, numBytes } = getBufferConfiguration(
|
|
302
|
-
targetBuffer?.type,
|
|
303
|
-
scalarLength,
|
|
304
|
-
{
|
|
305
|
-
use16BitTexture: useNorm16Texture,
|
|
306
|
-
isVolumeBuffer: true,
|
|
307
|
-
}
|
|
305
|
+
const { volumeScalarData, numBytes } = generateVolumeScalarData(
|
|
306
|
+
targetBuffer,
|
|
307
|
+
scalarLength
|
|
308
308
|
);
|
|
309
309
|
|
|
310
|
-
// check if there is enough space in unallocated + image Cache
|
|
311
|
-
const isCacheable = cache.isCacheable(numBytes);
|
|
312
|
-
if (!isCacheable) {
|
|
313
|
-
throw new Error(Events.CACHE_SIZE_EXCEEDED);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
let volumeScalarData;
|
|
317
|
-
if (targetBuffer?.sharedArrayBuffer) {
|
|
318
|
-
const buffer = new SharedArrayBuffer(numBytes);
|
|
319
|
-
volumeScalarData = new TypedArrayConstructor(buffer);
|
|
320
|
-
} else {
|
|
321
|
-
volumeScalarData = new TypedArrayConstructor(scalarLength);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
310
|
// Todo: handle more than one component for segmentation (RGB)
|
|
325
311
|
const scalarArray = vtkDataArray.newInstance({
|
|
326
312
|
name: 'Pixels',
|
|
@@ -346,7 +332,6 @@ export async function createAndCacheDerivedVolume(
|
|
|
346
332
|
imageData: derivedImageData,
|
|
347
333
|
scalarData: volumeScalarData,
|
|
348
334
|
sizeInBytes: numBytes,
|
|
349
|
-
referencedVolumeId,
|
|
350
335
|
imageIds: [],
|
|
351
336
|
});
|
|
352
337
|
|
|
@@ -374,21 +359,35 @@ export function createLocalVolume(
|
|
|
374
359
|
volumeId: string,
|
|
375
360
|
preventCache = false
|
|
376
361
|
): IImageVolume {
|
|
377
|
-
const {
|
|
362
|
+
const { metadata, dimensions, spacing, origin, direction, targetBuffer } =
|
|
378
363
|
options;
|
|
379
364
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
365
|
+
let { scalarData } = options;
|
|
366
|
+
|
|
367
|
+
// Define the valid data types for scalarData
|
|
368
|
+
const validDataTypes = [
|
|
369
|
+
'Uint8Array',
|
|
370
|
+
'Float32Array',
|
|
371
|
+
'Uint16Array',
|
|
372
|
+
'Int16Array',
|
|
373
|
+
];
|
|
374
|
+
|
|
375
|
+
const scalarLength = dimensions[0] * dimensions[1] * dimensions[2];
|
|
376
|
+
|
|
377
|
+
// Check if scalarData is provided and is of a valid type
|
|
378
|
+
if (!scalarData || !validDataTypes.includes(scalarData.constructor.name)) {
|
|
379
|
+
// Check if targetBuffer is provided and has a valid type
|
|
380
|
+
if (!targetBuffer?.type || !validDataTypes.includes(targetBuffer.type)) {
|
|
381
|
+
throw new Error(
|
|
382
|
+
'createLocalVolume: parameter scalarData must be provided and must be either Uint8Array, Float32Array, Uint16Array or Int16Array'
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Generate volume scalar data if scalarData is not provided or invalid
|
|
387
|
+
({ volumeScalarData: scalarData } = generateVolumeScalarData(
|
|
388
|
+
targetBuffer,
|
|
389
|
+
scalarLength
|
|
390
|
+
));
|
|
392
391
|
}
|
|
393
392
|
|
|
394
393
|
// Todo: handle default values for spacing, origin, direction if not provided
|
|
@@ -402,8 +401,6 @@ export function createLocalVolume(
|
|
|
402
401
|
return cachedVolume as IImageVolume;
|
|
403
402
|
}
|
|
404
403
|
|
|
405
|
-
const scalarLength = dimensions[0] * dimensions[1] * dimensions[2];
|
|
406
|
-
|
|
407
404
|
const numBytes = scalarData ? scalarData.buffer.byteLength : scalarLength * 4;
|
|
408
405
|
|
|
409
406
|
// check if there is enough space in unallocated + image Cache
|
|
@@ -436,7 +433,9 @@ export function createLocalVolume(
|
|
|
436
433
|
imageData: imageData,
|
|
437
434
|
scalarData,
|
|
438
435
|
sizeInBytes: numBytes,
|
|
439
|
-
|
|
436
|
+
referencedImageIds: options.referencedImageIds || [],
|
|
437
|
+
referencedVolumeId: options.referencedVolumeId,
|
|
438
|
+
imageIds: options.imageIds || [],
|
|
440
439
|
});
|
|
441
440
|
|
|
442
441
|
if (preventCache) {
|
|
@@ -573,7 +572,7 @@ export function getUnknownVolumeLoaderSchema(): string {
|
|
|
573
572
|
*/
|
|
574
573
|
export async function createAndCacheDerivedSegmentationVolume(
|
|
575
574
|
referencedVolumeId: string,
|
|
576
|
-
options
|
|
575
|
+
options = {} as DerivedVolumeOptions
|
|
577
576
|
): Promise<IImageVolume> {
|
|
578
577
|
return createAndCacheDerivedVolume(referencedVolumeId, {
|
|
579
578
|
...options,
|
|
@@ -582,3 +581,70 @@ export async function createAndCacheDerivedSegmentationVolume(
|
|
|
582
581
|
},
|
|
583
582
|
});
|
|
584
583
|
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Creates a local segmentation volume.
|
|
587
|
+
*
|
|
588
|
+
* @param options - The options for creating the volume.
|
|
589
|
+
* @param volumeId - The ID of the volume.
|
|
590
|
+
* @param preventCache - Whether to prevent caching the volume.
|
|
591
|
+
* @returns A promise that resolves to the created image volume.
|
|
592
|
+
*/
|
|
593
|
+
export async function createLocalSegmentationVolume(
|
|
594
|
+
options: LocalVolumeOptions,
|
|
595
|
+
volumeId: string,
|
|
596
|
+
preventCache = false
|
|
597
|
+
): Promise<IImageVolume> {
|
|
598
|
+
if (!options.scalarData) {
|
|
599
|
+
options.scalarData = new Uint8Array(
|
|
600
|
+
options.dimensions[0] * options.dimensions[1] * options.dimensions[2]
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
return createLocalVolume(options, volumeId, preventCache);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* This function generates volume scalar data based on the provided target buffer and scalar length.
|
|
609
|
+
* It checks if the cache can accommodate the data size and throws an error if it exceeds the cache size.
|
|
610
|
+
* If a shared array buffer is available in the target buffer, it uses that to create the typed array.
|
|
611
|
+
* Otherwise, it creates a typed array based on the scalar length.
|
|
612
|
+
*
|
|
613
|
+
* @param targetBuffer - The target buffer object which may contain a type and a shared array buffer.
|
|
614
|
+
* @param scalarLength - The scalar length for creating the typed array.
|
|
615
|
+
* @param useNorm16Texture - A flag to specify whether to use a 16-bit texture or not.
|
|
616
|
+
* @returns The volume scalar data as a typed array.
|
|
617
|
+
*/
|
|
618
|
+
function generateVolumeScalarData(
|
|
619
|
+
targetBuffer: {
|
|
620
|
+
type: PixelDataTypedArrayString;
|
|
621
|
+
sharedArrayBuffer?: boolean;
|
|
622
|
+
},
|
|
623
|
+
scalarLength: number
|
|
624
|
+
) {
|
|
625
|
+
const { useNorm16Texture } = getConfiguration().rendering;
|
|
626
|
+
|
|
627
|
+
const { TypedArrayConstructor, numBytes } = getBufferConfiguration(
|
|
628
|
+
targetBuffer?.type,
|
|
629
|
+
scalarLength,
|
|
630
|
+
{
|
|
631
|
+
use16BitTexture: useNorm16Texture,
|
|
632
|
+
isVolumeBuffer: true,
|
|
633
|
+
}
|
|
634
|
+
);
|
|
635
|
+
|
|
636
|
+
const isCacheable = cache.isCacheable(numBytes);
|
|
637
|
+
if (!isCacheable) {
|
|
638
|
+
throw new Error(Events.CACHE_SIZE_EXCEEDED);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
let volumeScalarData;
|
|
642
|
+
if (targetBuffer?.sharedArrayBuffer) {
|
|
643
|
+
const buffer = new SharedArrayBuffer(numBytes);
|
|
644
|
+
volumeScalarData = new TypedArrayConstructor(buffer);
|
|
645
|
+
} else {
|
|
646
|
+
volumeScalarData = new TypedArrayConstructor(scalarLength);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
return { volumeScalarData, numBytes };
|
|
650
|
+
}
|
|
@@ -120,7 +120,13 @@ class RequestPoolManager {
|
|
|
120
120
|
interaction: 6,
|
|
121
121
|
thumbnail: 6,
|
|
122
122
|
prefetch: 5,
|
|
123
|
-
|
|
123
|
+
// I believe there is a bug right now, where if there are two workers
|
|
124
|
+
// and one wants to run a compute job 6 times and the limit is just 5, then
|
|
125
|
+
// the other worker will never get a chance to run its compute job.
|
|
126
|
+
// we should probably have a separate limit for compute jobs per worker
|
|
127
|
+
// context as there is another layer of parallelism there. For this reason
|
|
128
|
+
// I'm setting the limit to 1000 for now.
|
|
129
|
+
compute: 1000,
|
|
124
130
|
};
|
|
125
131
|
}
|
|
126
132
|
|
package/src/types/IGeometry.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { Surface } from '../cache/classes/Surface';
|
|
2
1
|
import { GeometryType } from '../enums';
|
|
3
2
|
import { IContourSet } from './IContourSet';
|
|
3
|
+
import { ISurface } from './ISurface';
|
|
4
4
|
|
|
5
5
|
// interface IGeometry can be array of IContourSet
|
|
6
6
|
interface IGeometry {
|
|
7
7
|
id: string;
|
|
8
8
|
type: GeometryType;
|
|
9
|
-
data: IContourSet |
|
|
9
|
+
data: IContourSet | ISurface;
|
|
10
10
|
sizeInBytes: number;
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -81,10 +81,18 @@ interface IImageVolume {
|
|
|
81
81
|
destroy(): void;
|
|
82
82
|
|
|
83
83
|
/** decache */
|
|
84
|
-
decache?: () => void;
|
|
84
|
+
decache?: (completelyRemove?: boolean) => void;
|
|
85
85
|
|
|
86
86
|
/** */
|
|
87
87
|
get imageCacheOffsetMap(): Map<string, any>;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Mark the volume as having had the pixel data changed externally
|
|
91
|
+
* which in background will re-configure the volume to use the new
|
|
92
|
+
* pixel data.
|
|
93
|
+
*
|
|
94
|
+
*/
|
|
95
|
+
modified(): void;
|
|
88
96
|
}
|
|
89
97
|
|
|
90
98
|
export default IImageVolume;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import Point3 from './Point3';
|
|
2
|
+
|
|
3
|
+
export interface ISurface {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly sizeInBytes: number;
|
|
6
|
+
readonly frameOfReferenceUID: string;
|
|
7
|
+
getColor(): Point3;
|
|
8
|
+
setColor(color: Point3): void;
|
|
9
|
+
getPoints(): number[];
|
|
10
|
+
getPolys(): number[];
|
|
11
|
+
getSizeInBytes(): number;
|
|
12
|
+
setPoints(points: number[]): void;
|
|
13
|
+
setPolys(polys: number[]): void;
|
|
14
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -110,6 +110,7 @@ import type {
|
|
|
110
110
|
InternalVideoCamera,
|
|
111
111
|
VideoViewportInput,
|
|
112
112
|
} from './VideoViewportTypes';
|
|
113
|
+
import { ISurface } from './ISurface';
|
|
113
114
|
import type BoundsIJK from './BoundsIJK';
|
|
114
115
|
import type { ImageVolumeProps } from './ImageVolumeProps';
|
|
115
116
|
import type { VolumeProps } from './VolumeProps';
|
|
@@ -213,6 +214,7 @@ export type {
|
|
|
213
214
|
// Surface
|
|
214
215
|
PublicSurfaceData,
|
|
215
216
|
SurfaceData,
|
|
217
|
+
ISurface,
|
|
216
218
|
// Color
|
|
217
219
|
RGB,
|
|
218
220
|
ColormapPublic,
|
|
@@ -104,7 +104,7 @@ export default class VoxelManager<T> {
|
|
|
104
104
|
* Records the z index modified.
|
|
105
105
|
* Will record the index value if the VoxelManager is backed by a map.
|
|
106
106
|
*/
|
|
107
|
-
public setAtIJKPoint = ([i, j, k], v) => this.setAtIJK(i, j, k, v);
|
|
107
|
+
public setAtIJKPoint = ([i, j, k]: Point3, v) => this.setAtIJK(i, j, k, v);
|
|
108
108
|
|
|
109
109
|
/**
|
|
110
110
|
* Gets the value at the given index.
|
|
@@ -241,6 +241,12 @@ export default class VoxelManager<T> {
|
|
|
241
241
|
dimensions: Point3,
|
|
242
242
|
scalarData
|
|
243
243
|
): VoxelManager<number> {
|
|
244
|
+
if (dimensions.length !== 3) {
|
|
245
|
+
throw new Error(
|
|
246
|
+
'Dimensions must be provided as [number, number, number] for [width, height, depth]'
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
244
250
|
const voxels = new VoxelManager(
|
|
245
251
|
dimensions,
|
|
246
252
|
(index) => scalarData[index],
|
|
@@ -83,6 +83,30 @@ function _processImageCacheOffsetMap(volume, scalarData) {
|
|
|
83
83
|
* @param scalarData - The scalar data to use for the volume.
|
|
84
84
|
*/
|
|
85
85
|
function _processVolumeImages(volume, scalarData) {
|
|
86
|
+
let compatibleScalarData = scalarData;
|
|
87
|
+
|
|
88
|
+
const sampleImageIdWithImage = volume.imageIds.find((imageId) => {
|
|
89
|
+
const image = cache.getImage(imageId);
|
|
90
|
+
return image;
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (!sampleImageIdWithImage) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const sampleImage = cache.getImage(sampleImageIdWithImage);
|
|
98
|
+
const samplePixelData =
|
|
99
|
+
sampleImage.imageFrame?.pixelData || sampleImage.getPixelData();
|
|
100
|
+
|
|
101
|
+
// Check if the types of scalarData and pixelData are different.
|
|
102
|
+
if (scalarData.constructor !== samplePixelData.constructor) {
|
|
103
|
+
// If so, create a new typed array of the same type as pixelData and copy the values from scalarData.
|
|
104
|
+
compatibleScalarData = new samplePixelData.constructor(scalarData.length);
|
|
105
|
+
|
|
106
|
+
// Copy values from scalarData to compatibleScalarData.
|
|
107
|
+
compatibleScalarData.set(scalarData);
|
|
108
|
+
}
|
|
109
|
+
|
|
86
110
|
volume.imageIds.forEach((imageId) => {
|
|
87
111
|
const image = cache.getImage(imageId);
|
|
88
112
|
if (!image) {
|
|
@@ -92,7 +116,7 @@ function _processVolumeImages(volume, scalarData) {
|
|
|
92
116
|
const index = volume.getImageIdIndex(imageId);
|
|
93
117
|
const offset = index * image.getPixelData().byteLength;
|
|
94
118
|
|
|
95
|
-
_updateImageWithScalarDataView(image,
|
|
119
|
+
_updateImageWithScalarDataView(image, compatibleScalarData, offset);
|
|
96
120
|
cache.decrementImageCacheSize(image.sizeInBytes);
|
|
97
121
|
});
|
|
98
122
|
}
|
|
@@ -114,7 +114,7 @@ async function convertVolumeToStackViewport({
|
|
|
114
114
|
imageIdIndexToJump = minDistanceIndex;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
await stackViewport.setStack(stack, imageIdIndexToJump);
|
|
117
|
+
await stackViewport.setStack(stack, imageIdIndexToJump ?? 0);
|
|
118
118
|
|
|
119
119
|
// Render the image
|
|
120
120
|
stackViewport.render();
|
|
@@ -19,10 +19,9 @@ function generateVolumePropsFromImageIds(
|
|
|
19
19
|
getConfiguration().rendering;
|
|
20
20
|
|
|
21
21
|
const use16BitDataType = useNorm16Texture || preferSizeOverAccuracy;
|
|
22
|
-
|
|
23
22
|
const volumeMetadata = makeVolumeMetadata(imageIds);
|
|
24
23
|
|
|
25
|
-
// For a streaming volume, the data type cannot rely on
|
|
24
|
+
// For a streaming volume, the data type cannot rely on CSWIL to load
|
|
26
25
|
// the proper array buffer type. This is because the target buffer container
|
|
27
26
|
// must be decided ahead of time.
|
|
28
27
|
// TODO: move this logic into CSWIL to avoid logic duplication.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { VolumeViewport } from '../RenderingEngine';
|
|
2
|
+
import cache from '../cache';
|
|
3
|
+
import { IViewport, IStackViewport } from '../types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Retrieves the image IDs from the given viewport.
|
|
7
|
+
*
|
|
8
|
+
* @param viewport - The viewport to retrieve the image IDs from.
|
|
9
|
+
* @returns An array of image IDs.
|
|
10
|
+
*/
|
|
11
|
+
function getViewportImageIds(viewport: IViewport) {
|
|
12
|
+
if (viewport instanceof VolumeViewport) {
|
|
13
|
+
const defaultActor = viewport.getDefaultActor();
|
|
14
|
+
const volumeId = defaultActor.uid;
|
|
15
|
+
const volume = cache.getVolume(volumeId);
|
|
16
|
+
return volume.imageIds;
|
|
17
|
+
} else if ((viewport as IStackViewport).getImageIds) {
|
|
18
|
+
return (viewport as IStackViewport).getImageIds();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default getViewportImageIds;
|
package/src/utilities/index.ts
CHANGED
|
@@ -68,6 +68,7 @@ import { convertVolumeToStackViewport } from './convertVolumeToStackViewport';
|
|
|
68
68
|
import VoxelManager from './VoxelManager';
|
|
69
69
|
import roundNumber, { roundToPrecision } from './roundNumber';
|
|
70
70
|
import convertToGrayscale from './convertToGrayscale';
|
|
71
|
+
import getViewportImageIds from './getViewportImageIds';
|
|
71
72
|
|
|
72
73
|
// name spaces
|
|
73
74
|
import * as planar from './planar';
|
|
@@ -154,4 +155,5 @@ export {
|
|
|
154
155
|
cacheUtils,
|
|
155
156
|
roundNumber,
|
|
156
157
|
roundToPrecision,
|
|
158
|
+
getViewportImageIds,
|
|
157
159
|
};
|
|
@@ -6,11 +6,6 @@ class CentralizedWorkerManager {
|
|
|
6
6
|
constructor() {
|
|
7
7
|
this.workerRegistry = {};
|
|
8
8
|
this.workerPoolManager = new RequestPoolManager('webworker');
|
|
9
|
-
this.checkIntervalForIdleWorkers = 1000;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
setCheckIntervalForIdleWorkers(value) {
|
|
13
|
-
this.checkIntervalForIdleWorkers = value;
|
|
14
9
|
}
|
|
15
10
|
|
|
16
11
|
/**
|
|
@@ -29,7 +24,10 @@ class CentralizedWorkerManager {
|
|
|
29
24
|
const {
|
|
30
25
|
maxWorkerInstances = 1,
|
|
31
26
|
overwrite = false,
|
|
32
|
-
autoTerminateOnIdle =
|
|
27
|
+
autoTerminateOnIdle = {
|
|
28
|
+
enabled: false,
|
|
29
|
+
idleTimeThreshold: 3000, // 3 seconds
|
|
30
|
+
},
|
|
33
31
|
} = options;
|
|
34
32
|
|
|
35
33
|
if (this.workerRegistry[workerName] && !overwrite) {
|
|
@@ -43,25 +41,17 @@ class CentralizedWorkerManager {
|
|
|
43
41
|
|
|
44
42
|
const workerProperties = {
|
|
45
43
|
workerFn: null,
|
|
46
|
-
idleCheckIntervalId: null,
|
|
47
44
|
instances: [],
|
|
48
45
|
loadCounters: [],
|
|
49
46
|
lastActiveTime: [],
|
|
50
47
|
// used for termination
|
|
51
48
|
nativeWorkers: [],
|
|
49
|
+
// auto termination
|
|
50
|
+
autoTerminateOnIdle: autoTerminateOnIdle.enabled,
|
|
51
|
+
idleCheckIntervalId: null,
|
|
52
|
+
idleTimeThreshold: autoTerminateOnIdle.idleTimeThreshold,
|
|
52
53
|
};
|
|
53
54
|
|
|
54
|
-
if (
|
|
55
|
-
(autoTerminateOnIdle && !workerProperties.idleCheckIntervalId) ||
|
|
56
|
-
overwrite
|
|
57
|
-
) {
|
|
58
|
-
const idleCheckIntervalId = setInterval(() => {
|
|
59
|
-
this.terminateIdleWorkers(workerName, autoTerminateOnIdle);
|
|
60
|
-
}, this.checkIntervalForIdleWorkers);
|
|
61
|
-
|
|
62
|
-
workerProperties.idleCheckIntervalId = idleCheckIntervalId;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
55
|
workerProperties.loadCounters = Array(maxWorkerInstances).fill(0);
|
|
66
56
|
workerProperties.lastActiveTime = Array(maxWorkerInstances).fill(null);
|
|
67
57
|
|
|
@@ -90,7 +80,6 @@ class CentralizedWorkerManager {
|
|
|
90
80
|
|
|
91
81
|
let minLoadIndex = 0;
|
|
92
82
|
let minLoadValue = workerProperties.loadCounters[0] || 0;
|
|
93
|
-
|
|
94
83
|
for (let i = 1; i < workerInstances.length; i++) {
|
|
95
84
|
const currentLoadValue = workerProperties.loadCounters[i] || 0;
|
|
96
85
|
if (currentLoadValue < minLoadValue) {
|
|
@@ -121,7 +110,10 @@ class CentralizedWorkerManager {
|
|
|
121
110
|
*
|
|
122
111
|
* @param workerName - The name of the worker to execute the task on.
|
|
123
112
|
* @param methodName - The name of the method to execute on the worker.
|
|
124
|
-
* @param args - The arguments to pass to the method. Default is an
|
|
113
|
+
* @param args - The arguments to pass to the method. Default is an array
|
|
114
|
+
* You should put your transferable objects in the first argument as object
|
|
115
|
+
* and from the second argument you can put your non-transferable objects such
|
|
116
|
+
* as functions, classes, etc.
|
|
125
117
|
* @param options - An object containing options for the request. Default is an empty object.
|
|
126
118
|
* @param options.requestType - The type of the request. Default is RequestType.Compute.
|
|
127
119
|
* @param options.priority - The priority of the request. Default is 0.
|
|
@@ -133,7 +125,12 @@ class CentralizedWorkerManager {
|
|
|
133
125
|
workerName,
|
|
134
126
|
methodName,
|
|
135
127
|
args = {},
|
|
136
|
-
{
|
|
128
|
+
{
|
|
129
|
+
requestType = RequestType.Compute,
|
|
130
|
+
priority = 0,
|
|
131
|
+
options = {},
|
|
132
|
+
callbacks = [],
|
|
133
|
+
} = {}
|
|
137
134
|
) {
|
|
138
135
|
return new Promise((resolve, reject) => {
|
|
139
136
|
const requestFn = async () => {
|
|
@@ -148,11 +145,34 @@ class CentralizedWorkerManager {
|
|
|
148
145
|
}
|
|
149
146
|
|
|
150
147
|
try {
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
// fix if any of the args keys are a function then we need to proxy it
|
|
149
|
+
// for the worker to be able to call it
|
|
150
|
+
let finalCallbacks;
|
|
151
|
+
if (callbacks.length) {
|
|
152
|
+
finalCallbacks = callbacks.map((cb) => {
|
|
153
|
+
return Comlink.proxy(cb);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
153
156
|
const workerProperties = this.workerRegistry[workerName];
|
|
157
|
+
|
|
158
|
+
const results = await api[methodName](args, ...finalCallbacks);
|
|
159
|
+
|
|
154
160
|
workerProperties.lastActiveTime[index] = Date.now();
|
|
155
161
|
|
|
162
|
+
// If auto termination is enabled and the interval is not set, set it.
|
|
163
|
+
if (
|
|
164
|
+
workerProperties.autoTerminateOnIdle &&
|
|
165
|
+
!workerProperties.idleCheckIntervalId &&
|
|
166
|
+
workerProperties.idleTimeThreshold
|
|
167
|
+
) {
|
|
168
|
+
workerProperties.idleCheckIntervalId = setInterval(() => {
|
|
169
|
+
this.terminateIdleWorkers(
|
|
170
|
+
workerName,
|
|
171
|
+
workerProperties.idleTimeThreshold
|
|
172
|
+
);
|
|
173
|
+
}, workerProperties.idleTimeThreshold);
|
|
174
|
+
}
|
|
175
|
+
|
|
156
176
|
resolve(results);
|
|
157
177
|
} catch (err) {
|
|
158
178
|
console.error(
|
|
@@ -165,6 +185,11 @@ class CentralizedWorkerManager {
|
|
|
165
185
|
}
|
|
166
186
|
};
|
|
167
187
|
|
|
188
|
+
// I believe there is a bug right now, where if there are two workers
|
|
189
|
+
// and one wants to run a compute job 6 times and the limit is just 5, then
|
|
190
|
+
// the other worker will never get a chance to run its compute job.
|
|
191
|
+
// we should probably have a separate limit for compute jobs per worker
|
|
192
|
+
// context as there is another layer of parallelism there.
|
|
168
193
|
this.workerPoolManager.addRequest(
|
|
169
194
|
requestFn,
|
|
170
195
|
requestType,
|
|
@@ -176,24 +201,16 @@ class CentralizedWorkerManager {
|
|
|
176
201
|
|
|
177
202
|
terminateIdleWorkers(workerName, idleTimeThreshold) {
|
|
178
203
|
const workerProperties = this.workerRegistry[workerName];
|
|
179
|
-
|
|
180
204
|
const now = Date.now();
|
|
181
205
|
|
|
182
|
-
workerProperties.instances.forEach((
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const idleTime = now - workerProperties.lastActiveTime[index];
|
|
206
|
+
workerProperties.instances.forEach((_, index) => {
|
|
207
|
+
const lastActiveTime = workerProperties.lastActiveTime[index];
|
|
208
|
+
const isWorkerActive =
|
|
209
|
+
lastActiveTime !== null && workerProperties.loadCounters[index] > 0;
|
|
210
|
+
const idleTime = now - lastActiveTime;
|
|
189
211
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
workerInstance[Comlink.releaseProxy]();
|
|
193
|
-
workerProperties.nativeWorkers[index].terminate();
|
|
194
|
-
|
|
195
|
-
workerProperties.instances[index] = null;
|
|
196
|
-
workerProperties.lastActiveTime[index] = null;
|
|
212
|
+
if (!isWorkerActive && idleTime > idleTimeThreshold) {
|
|
213
|
+
this.terminateWorkerInstance(workerName, index);
|
|
197
214
|
}
|
|
198
215
|
});
|
|
199
216
|
}
|
|
@@ -205,13 +222,24 @@ class CentralizedWorkerManager {
|
|
|
205
222
|
return;
|
|
206
223
|
}
|
|
207
224
|
|
|
208
|
-
workerProperties.instances.forEach((
|
|
209
|
-
|
|
225
|
+
workerProperties.instances.forEach((_, index) => {
|
|
226
|
+
this.terminateWorkerInstance(workerName, index);
|
|
210
227
|
});
|
|
228
|
+
}
|
|
211
229
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
230
|
+
// New method to handle individual worker termination
|
|
231
|
+
terminateWorkerInstance(workerName, index) {
|
|
232
|
+
const workerProperties = this.workerRegistry[workerName];
|
|
233
|
+
const workerInstance = workerProperties.instances[index];
|
|
234
|
+
|
|
235
|
+
if (workerInstance !== null) {
|
|
236
|
+
workerInstance[Comlink.releaseProxy]();
|
|
237
|
+
workerProperties.nativeWorkers[index].terminate();
|
|
238
|
+
|
|
239
|
+
// Set the worker instance to null after termination
|
|
240
|
+
workerProperties.instances[index] = null;
|
|
241
|
+
workerProperties.lastActiveTime[index] = null;
|
|
242
|
+
}
|
|
215
243
|
}
|
|
216
244
|
}
|
|
217
245
|
|