@cornerstonejs/tools 3.8.3 → 3.8.5
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/esm/enums/WorkerTypes.d.ts +2 -1
- package/dist/esm/enums/WorkerTypes.js +1 -0
- package/dist/esm/stateManagement/segmentation/getViewportSegmentations.d.ts +2 -1
- package/dist/esm/stateManagement/segmentation/getViewportSegmentations.js +7 -3
- package/dist/esm/stateManagement/segmentation/helpers/getSegmentationActor.d.ts +0 -1
- package/dist/esm/stateManagement/segmentation/helpers/getSegmentationActor.js +0 -5
- package/dist/esm/stateManagement/segmentation/helpers/index.d.ts +2 -2
- package/dist/esm/stateManagement/segmentation/helpers/index.js +2 -2
- package/dist/esm/stateManagement/segmentation/internalAddSegmentationRepresentation.js +0 -2
- package/dist/esm/stateManagement/segmentation/segmentationState.d.ts +2 -2
- package/dist/esm/stateManagement/segmentation/segmentationState.js +2 -2
- package/dist/esm/tools/annotation/CircleROITool.js +7 -4
- package/dist/esm/tools/annotation/RegionSegmentPlusTool.js +8 -1
- package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js +3 -0
- package/dist/esm/tools/displayTools/Surface/removeSurfaceFromElement.js +3 -2
- package/dist/esm/tools/segmentation/BrushTool.js +1 -1
- package/dist/esm/utilities/contours/generateContourSetsFromLabelmap.d.ts +1 -1
- package/dist/esm/utilities/contours/generateContourSetsFromLabelmap.js +75 -95
- package/dist/esm/utilities/index.d.ts +2 -1
- package/dist/esm/utilities/index.js +2 -1
- package/dist/esm/utilities/segmentation/computeMetabolicStats.js +9 -0
- package/dist/esm/utilities/segmentation/contourAndFindLargestBidirectional.d.ts +1 -1
- package/dist/esm/utilities/segmentation/contourAndFindLargestBidirectional.js +2 -2
- package/dist/esm/utilities/segmentation/segmentContourAction.d.ts +1 -1
- package/dist/esm/utilities/segmentation/segmentContourAction.js +5 -4
- package/dist/esm/utilities/segmentation/utilsForWorker.js +3 -0
- package/dist/esm/workers/computeWorker.js +6 -2
- package/package.json +3 -3
|
@@ -6,6 +6,7 @@ declare enum ChangeTypes {
|
|
|
6
6
|
SURFACE_CLIPPING = "Clipping Surfaces",
|
|
7
7
|
COMPUTE_STATISTICS = "Computing Statistics",
|
|
8
8
|
INTERPOLATE_LABELMAP = "Interpolating Labelmap",
|
|
9
|
-
COMPUTE_LARGEST_BIDIRECTIONAL = "Computing Largest Bidirectional"
|
|
9
|
+
COMPUTE_LARGEST_BIDIRECTIONAL = "Computing Largest Bidirectional",
|
|
10
|
+
GENERATE_CONTOUR_SETS = "Generating Contour Sets"
|
|
10
11
|
}
|
|
11
12
|
export default ChangeTypes;
|
|
@@ -8,5 +8,6 @@ var ChangeTypes;
|
|
|
8
8
|
ChangeTypes["COMPUTE_STATISTICS"] = "Computing Statistics";
|
|
9
9
|
ChangeTypes["INTERPOLATE_LABELMAP"] = "Interpolating Labelmap";
|
|
10
10
|
ChangeTypes["COMPUTE_LARGEST_BIDIRECTIONAL"] = "Computing Largest Bidirectional";
|
|
11
|
+
ChangeTypes["GENERATE_CONTOUR_SETS"] = "Generating Contour Sets";
|
|
11
12
|
})(ChangeTypes || (ChangeTypes = {}));
|
|
12
13
|
export default ChangeTypes;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { SegmentationRepresentations } from '../../enums';
|
|
2
|
-
import type { Segmentation } from '../../types';
|
|
2
|
+
import type { Segmentation, SegmentationRepresentation } from '../../types';
|
|
3
3
|
export declare function getViewportSegmentations(viewportId: string, type?: SegmentationRepresentations): Segmentation[];
|
|
4
|
+
export declare function getViewportSegmentationRepresentations(viewportId: string): SegmentationRepresentation[];
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { getSegmentation } from './getSegmentation';
|
|
2
2
|
import { defaultSegmentationStateManager } from './SegmentationStateManager';
|
|
3
3
|
export function getViewportSegmentations(viewportId, type) {
|
|
4
|
-
const
|
|
5
|
-
const state = segmentationStateManager.getState();
|
|
6
|
-
const viewportRepresentations = state.viewportSegRepresentations[viewportId];
|
|
4
|
+
const viewportRepresentations = getViewportSegmentationRepresentations(viewportId);
|
|
7
5
|
const segmentations = viewportRepresentations.map((representation) => {
|
|
8
6
|
if (type && representation.type === type) {
|
|
9
7
|
return getSegmentation(representation.segmentationId);
|
|
@@ -13,3 +11,9 @@ export function getViewportSegmentations(viewportId, type) {
|
|
|
13
11
|
const filteredSegmentations = segmentations.filter((segmentation) => segmentation !== undefined);
|
|
14
12
|
return filteredSegmentations;
|
|
15
13
|
}
|
|
14
|
+
export function getViewportSegmentationRepresentations(viewportId) {
|
|
15
|
+
const segmentationStateManager = defaultSegmentationStateManager;
|
|
16
|
+
const state = segmentationStateManager.getState();
|
|
17
|
+
const viewportRepresentations = state.viewportSegRepresentations[viewportId];
|
|
18
|
+
return viewportRepresentations;
|
|
19
|
+
}
|
|
@@ -3,5 +3,4 @@ export declare function getLabelmapActorUID(viewportId: string, segmentationId:
|
|
|
3
3
|
export declare function getLabelmapActorEntries(viewportId: string, segmentationId: string): Types.ActorEntry[];
|
|
4
4
|
export declare function getLabelmapActorEntry(viewportId: string, segmentationId: string): Types.ActorEntry;
|
|
5
5
|
export declare function getSurfaceActorEntry(viewportId: string, segmentationId: string, segmentIndex?: number | string): Types.ActorEntry;
|
|
6
|
-
export declare function getSurfaceActorUID(viewportId: string, segmentationId: string, segmentIndex?: number | string): string | undefined;
|
|
7
6
|
export declare function getSurfaceRepresentationUID(segmentationId: string, segmentIndex?: number | string): string;
|
|
@@ -40,11 +40,6 @@ export function getSurfaceActorEntry(viewportId, segmentationId, segmentIndex) {
|
|
|
40
40
|
return getActorEntry(viewportId, segmentationId, (actor) => actor.representationUID ===
|
|
41
41
|
getSurfaceRepresentationUID(segmentationId, segmentIndex));
|
|
42
42
|
}
|
|
43
|
-
export function getSurfaceActorUID(viewportId, segmentationId, segmentIndex) {
|
|
44
|
-
const segIndex = segmentIndex ? segmentIndex.toString() : '';
|
|
45
|
-
const actorEntry = getSurfaceActorEntry(viewportId, segmentationId, segIndex);
|
|
46
|
-
return actorEntry?.uid;
|
|
47
|
-
}
|
|
48
43
|
export function getSurfaceRepresentationUID(segmentationId, segmentIndex) {
|
|
49
44
|
return `${segmentationId}-${SegmentationRepresentations.Surface}-${segmentIndex}`;
|
|
50
45
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import validateSegmentationInput from './validateSegmentationInput';
|
|
2
|
-
import { getLabelmapActorEntries, getLabelmapActorEntry, getSurfaceActorEntry, getLabelmapActorUID
|
|
3
|
-
export { validateSegmentationInput, getLabelmapActorEntries, getLabelmapActorEntry, getSurfaceActorEntry, getLabelmapActorUID,
|
|
2
|
+
import { getLabelmapActorEntries, getLabelmapActorEntry, getSurfaceActorEntry, getLabelmapActorUID } from './getSegmentationActor';
|
|
3
|
+
export { validateSegmentationInput, getLabelmapActorEntries, getLabelmapActorEntry, getSurfaceActorEntry, getLabelmapActorUID, };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import validateSegmentationInput from './validateSegmentationInput';
|
|
2
|
-
import { getLabelmapActorEntries, getLabelmapActorEntry, getSurfaceActorEntry, getLabelmapActorUID,
|
|
3
|
-
export { validateSegmentationInput, getLabelmapActorEntries, getLabelmapActorEntry, getSurfaceActorEntry, getLabelmapActorUID,
|
|
2
|
+
import { getLabelmapActorEntries, getLabelmapActorEntry, getSurfaceActorEntry, getLabelmapActorUID, } from './getSegmentationActor';
|
|
3
|
+
export { validateSegmentationInput, getLabelmapActorEntries, getLabelmapActorEntry, getSurfaceActorEntry, getLabelmapActorUID, };
|
|
@@ -3,9 +3,7 @@ import { triggerAnnotationRenderForViewportIds } from '../../utilities/triggerAn
|
|
|
3
3
|
import { SegmentationRepresentations } from '../../enums';
|
|
4
4
|
import { triggerSegmentationModified } from './triggerSegmentationEvents';
|
|
5
5
|
import { addColorLUT } from './addColorLUT';
|
|
6
|
-
import { getNextColorLUTIndex } from './getNextColorLUTIndex';
|
|
7
6
|
import { defaultSegmentationStateManager } from './SegmentationStateManager';
|
|
8
|
-
import { getColorLUT } from './getColorLUT';
|
|
9
7
|
function internalAddSegmentationRepresentation(viewportId, representationInput) {
|
|
10
8
|
const { segmentationId, config } = representationInput;
|
|
11
9
|
const renderingConfig = {
|
|
@@ -7,11 +7,11 @@ import { addColorLUT } from './addColorLUT';
|
|
|
7
7
|
import { getColorLUT } from './getColorLUT';
|
|
8
8
|
import { getNextColorLUTIndex } from './getNextColorLUTIndex';
|
|
9
9
|
import { removeColorLUT } from './removeColorLUT';
|
|
10
|
-
import { getViewportSegmentations } from './getViewportSegmentations';
|
|
10
|
+
import { getViewportSegmentations, getViewportSegmentationRepresentations } from './getViewportSegmentations';
|
|
11
11
|
import { getViewportIdsWithSegmentation } from './getViewportIdsWithSegmentation';
|
|
12
12
|
import { getCurrentLabelmapImageIdForViewport, getCurrentLabelmapImageIdsForViewport } from './getCurrentLabelmapImageIdForViewport';
|
|
13
13
|
import { updateLabelmapSegmentationImageReferences } from './updateLabelmapSegmentationImageReferences';
|
|
14
14
|
import { getStackSegmentationImageIdsForViewport } from './getStackSegmentationImageIdsForViewport';
|
|
15
15
|
import { getSegmentationRepresentation, getSegmentationRepresentations, getSegmentationRepresentationsBySegmentationId } from './getSegmentationRepresentation';
|
|
16
16
|
declare function destroy(): void;
|
|
17
|
-
export { getColorLUT, getCurrentLabelmapImageIdForViewport, getCurrentLabelmapImageIdsForViewport, getNextColorLUTIndex, getSegmentation, getSegmentations, getStackSegmentationImageIdsForViewport, getViewportIdsWithSegmentation, getSegmentationRepresentation, getSegmentationRepresentations, removeColorLUT, getViewportSegmentations, removeSegmentation, removeLabelmapRepresentation, removeContourRepresentation, removeSurfaceRepresentation, removeSegmentationRepresentation, removeAllSegmentationRepresentations, removeAllSegmentations, addColorLUT, addSegmentations, updateLabelmapSegmentationImageReferences, getSegmentationRepresentationsBySegmentationId, destroy, };
|
|
17
|
+
export { getColorLUT, getCurrentLabelmapImageIdForViewport, getCurrentLabelmapImageIdsForViewport, getNextColorLUTIndex, getSegmentation, getSegmentations, getStackSegmentationImageIdsForViewport, getViewportIdsWithSegmentation, getSegmentationRepresentation, getSegmentationRepresentations, getViewportSegmentationRepresentations, removeColorLUT, getViewportSegmentations, removeSegmentation, removeLabelmapRepresentation, removeContourRepresentation, removeSurfaceRepresentation, removeSegmentationRepresentation, removeAllSegmentationRepresentations, removeAllSegmentations, addColorLUT, addSegmentations, updateLabelmapSegmentationImageReferences, getSegmentationRepresentationsBySegmentationId, destroy, };
|
|
@@ -7,7 +7,7 @@ import { addColorLUT } from './addColorLUT';
|
|
|
7
7
|
import { getColorLUT } from './getColorLUT';
|
|
8
8
|
import { getNextColorLUTIndex } from './getNextColorLUTIndex';
|
|
9
9
|
import { removeColorLUT } from './removeColorLUT';
|
|
10
|
-
import { getViewportSegmentations } from './getViewportSegmentations';
|
|
10
|
+
import { getViewportSegmentations, getViewportSegmentationRepresentations, } from './getViewportSegmentations';
|
|
11
11
|
import { getViewportIdsWithSegmentation } from './getViewportIdsWithSegmentation';
|
|
12
12
|
import { getCurrentLabelmapImageIdForViewport, getCurrentLabelmapImageIdsForViewport, } from './getCurrentLabelmapImageIdForViewport';
|
|
13
13
|
import { updateLabelmapSegmentationImageReferences } from './updateLabelmapSegmentationImageReferences';
|
|
@@ -17,4 +17,4 @@ import { defaultSegmentationStateManager } from './SegmentationStateManager';
|
|
|
17
17
|
function destroy() {
|
|
18
18
|
defaultSegmentationStateManager.resetState();
|
|
19
19
|
}
|
|
20
|
-
export { getColorLUT, getCurrentLabelmapImageIdForViewport, getCurrentLabelmapImageIdsForViewport, getNextColorLUTIndex, getSegmentation, getSegmentations, getStackSegmentationImageIdsForViewport, getViewportIdsWithSegmentation, getSegmentationRepresentation, getSegmentationRepresentations, removeColorLUT, getViewportSegmentations, removeSegmentation, removeLabelmapRepresentation, removeContourRepresentation, removeSurfaceRepresentation, removeSegmentationRepresentation, removeAllSegmentationRepresentations, removeAllSegmentations, addColorLUT, addSegmentations, updateLabelmapSegmentationImageReferences, getSegmentationRepresentationsBySegmentationId, destroy, };
|
|
20
|
+
export { getColorLUT, getCurrentLabelmapImageIdForViewport, getCurrentLabelmapImageIdsForViewport, getNextColorLUTIndex, getSegmentation, getSegmentations, getStackSegmentationImageIdsForViewport, getViewportIdsWithSegmentation, getSegmentationRepresentation, getSegmentationRepresentations, getViewportSegmentationRepresentations, removeColorLUT, getViewportSegmentations, removeSegmentation, removeLabelmapRepresentation, removeContourRepresentation, removeSurfaceRepresentation, removeSegmentationRepresentation, removeAllSegmentationRepresentations, removeAllSegmentations, addColorLUT, addSegmentations, updateLabelmapSegmentationImageReferences, getSegmentationRepresentationsBySegmentationId, destroy, };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AnnotationTool } from '../base';
|
|
2
|
-
import { getEnabledElement, VolumeViewport, utilities as csUtils, getEnabledElementByViewportId, } from '@cornerstonejs/core';
|
|
2
|
+
import { getEnabledElement, VolumeViewport, utilities as csUtils, getEnabledElementByViewportId, EPSILON, } from '@cornerstonejs/core';
|
|
3
3
|
import { getCalibratedAspect, getCalibratedLengthUnitsAndScale, } from '../../utilities/getCalibratedUnits';
|
|
4
4
|
import throttle from '../../utilities/throttle';
|
|
5
5
|
import { addAnnotation, getAnnotations, removeAnnotation, } from '../../stateManagement/annotation/annotationState';
|
|
@@ -507,11 +507,14 @@ class CircleROITool extends AnnotationTool {
|
|
|
507
507
|
(topLeftWorld[1] + bottomRightWorld[1]) / 2,
|
|
508
508
|
(topLeftWorld[2] + bottomRightWorld[2]) / 2,
|
|
509
509
|
];
|
|
510
|
+
const xRadius = Math.abs(topLeftWorld[0] - bottomRightWorld[0]) / 2;
|
|
511
|
+
const yRadius = Math.abs(topLeftWorld[1] - bottomRightWorld[1]) / 2;
|
|
512
|
+
const zRadius = Math.abs(topLeftWorld[2] - bottomRightWorld[2]) / 2;
|
|
510
513
|
const ellipseObj = {
|
|
511
514
|
center,
|
|
512
|
-
xRadius:
|
|
513
|
-
yRadius:
|
|
514
|
-
zRadius:
|
|
515
|
+
xRadius: xRadius < EPSILON / 2 ? 0 : xRadius,
|
|
516
|
+
yRadius: yRadius < EPSILON / 2 ? 0 : yRadius,
|
|
517
|
+
zRadius: zRadius < EPSILON / 2 ? 0 : zRadius,
|
|
515
518
|
};
|
|
516
519
|
const { worldWidth, worldHeight } = getWorldWidthAndHeightFromTwoPoints(viewPlaneNormal, viewUp, worldPos1, worldPos2);
|
|
517
520
|
const isEmptyArea = worldWidth === 0 && worldHeight === 0;
|
|
@@ -2,6 +2,7 @@ import { cache, utilities as csUtils, getEnabledElement, } from '@cornerstonejs/
|
|
|
2
2
|
import { growCut } from '../../utilities/segmentation';
|
|
3
3
|
import GrowCutBaseTool from '../base/GrowCutBaseTool';
|
|
4
4
|
import { calculateGrowCutSeeds } from '../../utilities/segmentation/growCut/runOneClickGrowCut';
|
|
5
|
+
import { ToolModes } from '../../enums';
|
|
5
6
|
class RegionSegmentPlusTool extends GrowCutBaseTool {
|
|
6
7
|
static { this.toolName = 'RegionSegmentPlus'; }
|
|
7
8
|
constructor(toolProps = {}, defaultToolProps = {
|
|
@@ -21,6 +22,9 @@ class RegionSegmentPlusTool extends GrowCutBaseTool {
|
|
|
21
22
|
this.allowedToProceed = false;
|
|
22
23
|
}
|
|
23
24
|
mouseMoveCallback(evt) {
|
|
25
|
+
if (this.mode !== ToolModes.Active) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
24
28
|
const eventData = evt.detail;
|
|
25
29
|
const { currentPoints, element } = eventData;
|
|
26
30
|
const { world: worldPoint } = currentPoints;
|
|
@@ -36,7 +40,10 @@ class RegionSegmentPlusTool extends GrowCutBaseTool {
|
|
|
36
40
|
async onMouseStable(evt, worldPoint, element) {
|
|
37
41
|
await super.preMouseDownCallback(evt);
|
|
38
42
|
const refVolume = cache.getVolume(this.growCutData.segmentation.referencedVolumeId);
|
|
39
|
-
const seeds = calculateGrowCutSeeds(refVolume, worldPoint, {})
|
|
43
|
+
const seeds = calculateGrowCutSeeds(refVolume, worldPoint, {}) || {
|
|
44
|
+
positiveSeedIndices: new Set(),
|
|
45
|
+
negativeSeedIndices: new Set(),
|
|
46
|
+
};
|
|
40
47
|
const { positiveSeedIndices, negativeSeedIndices } = seeds;
|
|
41
48
|
let cursor;
|
|
42
49
|
if (positiveSeedIndices.size / negativeSeedIndices.size > 20 ||
|
|
@@ -172,6 +172,9 @@ function _setLabelmapColorAndOpacity(viewportId, labelmapActorEntry, segmentatio
|
|
|
172
172
|
: outlineWidth;
|
|
173
173
|
}
|
|
174
174
|
labelmapActor.getProperty().setLabelOutlineThickness(outlineWidths);
|
|
175
|
+
labelmapActor.modified();
|
|
176
|
+
labelmapActor.getProperty().modified();
|
|
177
|
+
labelmapActor.getMapper().modified();
|
|
175
178
|
}
|
|
176
179
|
else {
|
|
177
180
|
labelmapActor
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { getEnabledElement } from '@cornerstonejs/core';
|
|
2
|
-
import { getSurfaceActorUID } from '../../../stateManagement/segmentation/helpers/getSegmentationActor';
|
|
3
2
|
function removeSurfaceFromElement(element, segmentationId) {
|
|
4
3
|
const enabledElement = getEnabledElement(element);
|
|
5
4
|
const { viewport } = enabledElement;
|
|
6
5
|
const actorEntries = viewport.getActors();
|
|
7
|
-
const filteredSurfaceActors = actorEntries.filter((actor) => actor.
|
|
6
|
+
const filteredSurfaceActors = actorEntries.filter((actor) => actor.representationUID &&
|
|
7
|
+
typeof actor.representationUID === 'string' &&
|
|
8
|
+
actor.representationUID.startsWith(segmentationId));
|
|
8
9
|
viewport.removeActors(filteredSurfaceActors.map((actor) => actor.uid));
|
|
9
10
|
}
|
|
10
11
|
export default removeSurfaceFromElement;
|
|
@@ -200,8 +200,8 @@ class BrushTool extends LabelmapBaseTool {
|
|
|
200
200
|
const operationData = this.getOperationData(element);
|
|
201
201
|
if (!this._previewData.preview && !this._previewData.isDrag) {
|
|
202
202
|
this.applyActiveStrategy(enabledElement, operationData);
|
|
203
|
-
this.doneEditMemo();
|
|
204
203
|
}
|
|
204
|
+
this.doneEditMemo();
|
|
205
205
|
this._deactivateDraw(element);
|
|
206
206
|
resetElementCursor(element);
|
|
207
207
|
this.updateCursor(evt);
|
|
@@ -1,111 +1,91 @@
|
|
|
1
|
-
import { cache as cornerstoneCache } from '@cornerstonejs/core';
|
|
2
|
-
import vtkImageMarchingSquares from '@kitware/vtk.js/Filters/General/ImageMarchingSquares';
|
|
3
|
-
import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
|
|
4
|
-
import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
|
|
5
|
-
import { getDeduplicatedVTKPolyDataPoints } from './getDeduplicatedVTKPolyDataPoints';
|
|
6
|
-
import { findContoursFromReducedSet } from './contourFinder';
|
|
1
|
+
import { cache as cornerstoneCache, getWebWorkerManager, cache, utilities, } from '@cornerstonejs/core';
|
|
7
2
|
import SegmentationRepresentations from '../../enums/SegmentationRepresentations';
|
|
3
|
+
import { WorkerTypes } from '../../enums';
|
|
4
|
+
import { registerComputeWorker } from '../registerComputeWorker';
|
|
5
|
+
import { triggerWorkerProgress } from '../segmentation/utilsForWorker';
|
|
6
|
+
import getOrCreateSegmentationVolume from '../segmentation/getOrCreateSegmentationVolume';
|
|
8
7
|
const { Labelmap } = SegmentationRepresentations;
|
|
9
|
-
function generateContourSetsFromLabelmap({ segmentations }) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const {
|
|
8
|
+
async function generateContourSetsFromLabelmap({ segmentations }) {
|
|
9
|
+
registerComputeWorker();
|
|
10
|
+
triggerWorkerProgress(WorkerTypes.GENERATE_CONTOUR_SETS, 0);
|
|
11
|
+
const { representationData, segments = [0, 1], segmentationId, } = segmentations;
|
|
12
|
+
let { volumeId: segVolumeId } = representationData[Labelmap];
|
|
13
|
+
if (!segVolumeId) {
|
|
14
|
+
const segVolume = getOrCreateSegmentationVolume(segmentationId);
|
|
15
|
+
if (segVolume) {
|
|
16
|
+
segVolumeId = segVolume.volumeId;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
13
19
|
const vol = cornerstoneCache.getVolume(segVolumeId);
|
|
14
20
|
if (!vol) {
|
|
15
21
|
console.warn(`No volume found for ${segVolumeId}`);
|
|
16
22
|
return;
|
|
17
23
|
}
|
|
18
24
|
const voxelManager = vol.voxelManager;
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
const segScalarData = voxelManager.getCompleteScalarDataArray();
|
|
26
|
+
const segmentationInfo = {
|
|
27
|
+
scalarData: segScalarData,
|
|
28
|
+
dimensions: vol.dimensions,
|
|
29
|
+
spacing: vol.imageData.getSpacing(),
|
|
30
|
+
origin: vol.imageData.getOrigin(),
|
|
31
|
+
direction: vol.imageData.getDirection(),
|
|
32
|
+
};
|
|
33
|
+
const indices = Array.isArray(segments)
|
|
34
|
+
? segments
|
|
35
|
+
.filter((segment) => segment !== null)
|
|
36
|
+
.map((segment) => segment.segmentIndex || segment)
|
|
37
|
+
: Object.values(segments)
|
|
38
|
+
.filter((segment) => segment !== null)
|
|
39
|
+
.map((segment) => segment.segmentIndex || segment);
|
|
40
|
+
const contourSets = await getWebWorkerManager().executeTask('compute', 'generateContourSetsFromLabelmapVolume', {
|
|
41
|
+
segmentation: segmentationInfo,
|
|
42
|
+
indices,
|
|
43
|
+
mode: 'individual',
|
|
44
|
+
});
|
|
45
|
+
const refImages = vol.imageIds.map((imageId) => {
|
|
46
|
+
const refImageId = cache.getImage(imageId)?.referencedImageId;
|
|
47
|
+
return refImageId ? cache.getImage(refImageId) : undefined;
|
|
48
|
+
});
|
|
49
|
+
const refImageDataMetadata = refImages.map((image) => {
|
|
50
|
+
return utilities.getImageDataMetadata(image);
|
|
51
|
+
});
|
|
52
|
+
const processedContourSets = contourSets
|
|
53
|
+
.map((contourSet) => {
|
|
54
|
+
const segment = segments[contourSet.segment.segmentIndex] || {};
|
|
55
|
+
if (!contourSet.sliceContours.length) {
|
|
56
|
+
return null;
|
|
36
57
|
}
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
const frameStart = sliceIndex * pixelsPerSlice;
|
|
50
|
-
try {
|
|
51
|
-
for (let i = 0; i < pixelsPerSlice; i++) {
|
|
52
|
-
const value = segData[i + frameStart];
|
|
53
|
-
if (value === segIndex || containedSegmentIndices?.has(value)) {
|
|
54
|
-
scalars.setValue(i + frameStart, 1);
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
scalars.setValue(i, 0);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
const mSquares = vtkImageMarchingSquares.newInstance({
|
|
61
|
-
slice: sliceIndex,
|
|
62
|
-
});
|
|
63
|
-
const imageDataCopy = vtkImageData.newInstance();
|
|
64
|
-
imageDataCopy.shallowCopy(vol.imageData);
|
|
65
|
-
imageDataCopy.getPointData().setScalars(scalars);
|
|
66
|
-
mSquares.setInputData(imageDataCopy);
|
|
67
|
-
const cValues = [1];
|
|
68
|
-
mSquares.setContourValues(cValues);
|
|
69
|
-
mSquares.setMergePoints(false);
|
|
70
|
-
const msOutput = mSquares.getOutputData();
|
|
71
|
-
const reducedSet = getDeduplicatedVTKPolyDataPoints(msOutput);
|
|
72
|
-
if (reducedSet.points?.length) {
|
|
73
|
-
const contours = findContoursFromReducedSet(reducedSet.lines);
|
|
74
|
-
sliceContours.push({
|
|
75
|
-
contours,
|
|
76
|
-
polyData: reducedSet,
|
|
77
|
-
FrameNumber: sliceIndex + 1,
|
|
78
|
-
sliceIndex,
|
|
79
|
-
FrameOfReferenceUID,
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
catch (e) {
|
|
84
|
-
console.warn(sliceIndex);
|
|
85
|
-
console.warn(e);
|
|
58
|
+
const p1 = contourSet.sliceContours[0].polyData.points[0];
|
|
59
|
+
let refImageId;
|
|
60
|
+
if (p1) {
|
|
61
|
+
const refImageIndex = refImageDataMetadata.findIndex((imageDataMetadata) => {
|
|
62
|
+
const { scanAxisNormal, origin } = imageDataMetadata;
|
|
63
|
+
const plane = utilities.planar.planeEquation(scanAxisNormal, origin);
|
|
64
|
+
return utilities.planar.isPointOnPlane(p1, plane);
|
|
65
|
+
});
|
|
66
|
+
if (refImageIndex !== -1) {
|
|
67
|
+
refImageId = refImages[refImageIndex].imageId;
|
|
86
68
|
}
|
|
87
69
|
}
|
|
88
|
-
|
|
89
|
-
FrameOfReferenceUID,
|
|
90
|
-
};
|
|
91
|
-
const ContourSet = {
|
|
70
|
+
return {
|
|
92
71
|
label: segment.label,
|
|
93
72
|
color: segment.color,
|
|
94
|
-
metadata
|
|
95
|
-
|
|
73
|
+
metadata: {
|
|
74
|
+
FrameOfReferenceUID: vol.metadata.FrameOfReferenceUID,
|
|
75
|
+
referencedImageId: refImageId,
|
|
76
|
+
},
|
|
77
|
+
sliceContours: contourSet.sliceContours.map((contourData) => ({
|
|
78
|
+
contours: contourData.contours,
|
|
79
|
+
polyData: contourData.polyData,
|
|
80
|
+
FrameNumber: contourData.sliceIndex + 1,
|
|
81
|
+
sliceIndex: contourData.sliceIndex,
|
|
82
|
+
FrameOfReferenceUID: vol.metadata.FrameOfReferenceUID,
|
|
83
|
+
referencedImageId: refImageId,
|
|
84
|
+
})),
|
|
96
85
|
};
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
function isSliceEmptyForSegment(sliceIndex, segData, pixelsPerSlice, segIndex) {
|
|
102
|
-
const startIdx = sliceIndex * pixelsPerSlice;
|
|
103
|
-
const endIdx = startIdx + pixelsPerSlice;
|
|
104
|
-
for (let i = startIdx; i < endIdx; i++) {
|
|
105
|
-
if (segData[i] === segIndex) {
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return true;
|
|
86
|
+
})
|
|
87
|
+
.filter((contourSet) => contourSet !== null);
|
|
88
|
+
triggerWorkerProgress(WorkerTypes.GENERATE_CONTOUR_SETS, 100);
|
|
89
|
+
return processedContourSets;
|
|
110
90
|
}
|
|
111
91
|
export { generateContourSetsFromLabelmap };
|
|
@@ -39,4 +39,5 @@ import { getPixelValueUnits, getPixelValueUnitsImageId } from './getPixelValueUn
|
|
|
39
39
|
import * as geometricSurfaceUtils from './geometricSurfaceUtils';
|
|
40
40
|
import setAnnotationLabel from './setAnnotationLabel';
|
|
41
41
|
import { moveAnnotationToViewPlane } from './moveAnnotationToViewPlane';
|
|
42
|
-
|
|
42
|
+
import getOrCreateImageVolume from './segmentation/getOrCreateImageVolume';
|
|
43
|
+
export { math, planar, viewportFilters, drawing, debounce, dynamicVolume, throttle, orientation, isObject, touch, triggerEvent, calibrateImageSpacing, getCalibratedLengthUnitsAndScale, getCalibratedProbeUnitsAndValue, getCalibratedAspect, getPixelValueUnits, getPixelValueUnitsImageId, segmentation, contours, triggerAnnotationRenderForViewportIds, triggerAnnotationRenderForToolGroupIds, triggerAnnotationRender, getSphereBoundsInfo, getAnnotationNearPoint, getViewportForAnnotation, getAnnotationNearPointOnEnabledElement, viewport, cine, boundingBox, rectangleROITool, planarFreehandROITool, stackPrefetch, stackContextPrefetch, roundNumber, pointToString, polyDataUtils, voi, AnnotationMultiSlice, contourSegmentation, annotationHydration, getClosestImageIdForStackViewport, pointInSurroundingSphereCallback, normalizeViewportPlane, IslandRemoval, geometricSurfaceUtils, setAnnotationLabel, moveAnnotationToViewPlane, getOrCreateImageVolume, };
|
|
@@ -39,4 +39,5 @@ import { getPixelValueUnits, getPixelValueUnitsImageId, } from './getPixelValueU
|
|
|
39
39
|
import * as geometricSurfaceUtils from './geometricSurfaceUtils';
|
|
40
40
|
import setAnnotationLabel from './setAnnotationLabel';
|
|
41
41
|
import { moveAnnotationToViewPlane } from './moveAnnotationToViewPlane';
|
|
42
|
-
|
|
42
|
+
import getOrCreateImageVolume from './segmentation/getOrCreateImageVolume';
|
|
43
|
+
export { math, planar, viewportFilters, drawing, debounce, dynamicVolume, throttle, orientation, isObject, touch, triggerEvent, calibrateImageSpacing, getCalibratedLengthUnitsAndScale, getCalibratedProbeUnitsAndValue, getCalibratedAspect, getPixelValueUnits, getPixelValueUnitsImageId, segmentation, contours, triggerAnnotationRenderForViewportIds, triggerAnnotationRenderForToolGroupIds, triggerAnnotationRender, getSphereBoundsInfo, getAnnotationNearPoint, getViewportForAnnotation, getAnnotationNearPointOnEnabledElement, viewport, cine, boundingBox, rectangleROITool, planarFreehandROITool, stackPrefetch, stackContextPrefetch, roundNumber, pointToString, polyDataUtils, voi, AnnotationMultiSlice, contourSegmentation, annotationHydration, getClosestImageIdForStackViewport, pointInSurroundingSphereCallback, normalizeViewportPlane, IslandRemoval, geometricSurfaceUtils, setAnnotationLabel, moveAnnotationToViewPlane, getOrCreateImageVolume, };
|
|
@@ -48,6 +48,15 @@ async function calculateForVolume({ segmentationIds, segmentIndex }) {
|
|
|
48
48
|
direction: referenceVolume.direction,
|
|
49
49
|
scalarData: referenceVolume.voxelManager.getCompleteScalarDataArray(),
|
|
50
50
|
};
|
|
51
|
+
if (imageInfo.scalarData.length === 0 ||
|
|
52
|
+
segmentationInfo.scalarData.length === 0) {
|
|
53
|
+
return {
|
|
54
|
+
[segmentIndex]: {
|
|
55
|
+
name: 'TMTV',
|
|
56
|
+
value: 0,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
51
60
|
const stats = await getWebWorkerManager().executeTask('compute', 'computeMetabolicStats', {
|
|
52
61
|
segmentationInfo,
|
|
53
62
|
imageInfo,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export default function contourAndFindLargestBidirectional(segmentation: any): any
|
|
1
|
+
export default function contourAndFindLargestBidirectional(segmentation: any): Promise<any>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { generateContourSetsFromLabelmap } from '../contours';
|
|
2
2
|
import findLargestBidirectional from './findLargestBidirectional';
|
|
3
3
|
import getOrCreateSegmentationVolume from './getOrCreateSegmentationVolume';
|
|
4
|
-
export default function contourAndFindLargestBidirectional(segmentation) {
|
|
5
|
-
const contours = generateContourSetsFromLabelmap({
|
|
4
|
+
export default async function contourAndFindLargestBidirectional(segmentation) {
|
|
5
|
+
const contours = await generateContourSetsFromLabelmap({
|
|
6
6
|
segmentations: segmentation,
|
|
7
7
|
});
|
|
8
8
|
if (!contours?.length || !contours[0].sliceContours.length) {
|
|
@@ -13,5 +13,5 @@ export type SegmentContourActionConfiguration = {
|
|
|
13
13
|
segmentData?: Map<number, Segment>;
|
|
14
14
|
toolGroupId?: string;
|
|
15
15
|
};
|
|
16
|
-
export default function segmentContourAction(element: HTMLDivElement, configuration: any): any
|
|
16
|
+
export default function segmentContourAction(element: HTMLDivElement, configuration: any): Promise<any>;
|
|
17
17
|
export declare function defaultGetSegment(enabledElement: Types.IEnabledElement, configuration: SegmentContourActionConfiguration): Segment;
|
|
@@ -5,7 +5,7 @@ import createBidirectionalToolData from './createBidirectionalToolData';
|
|
|
5
5
|
import BidirectionalTool from '../../tools/annotation/BidirectionalTool';
|
|
6
6
|
import { getSegmentations } from '../../stateManagement/segmentation/getSegmentations';
|
|
7
7
|
import { getActiveSegmentIndex } from '../../stateManagement/segmentation/getActiveSegmentIndex';
|
|
8
|
-
export default function segmentContourAction(element, configuration) {
|
|
8
|
+
export default async function segmentContourAction(element, configuration) {
|
|
9
9
|
console.warn('Deprecation Alert: There is a new getSegmentLargestBidirectional function that handles volume, stack and individual segment cases properly. This function is deprecated and will be removed in a future version.');
|
|
10
10
|
const { data: configurationData } = configuration;
|
|
11
11
|
const enabledElement = getEnabledElement(element);
|
|
@@ -36,13 +36,14 @@ export default function segmentContourAction(element, configuration) {
|
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
let newBidirectional;
|
|
39
|
-
existingLargestBidirectionals.forEach((existingLargestBidirectional) => {
|
|
39
|
+
existingLargestBidirectionals.forEach(async (existingLargestBidirectional) => {
|
|
40
40
|
const segments = [];
|
|
41
|
-
const updateSegment = existingLargestBidirectional.data
|
|
41
|
+
const updateSegment = existingLargestBidirectional.data
|
|
42
|
+
.segment;
|
|
42
43
|
const { segmentIndex, segmentationId } = updateSegment;
|
|
43
44
|
segments[segmentIndex] = updateSegment;
|
|
44
45
|
annotationState.removeAnnotation(existingLargestBidirectional.annotationUID);
|
|
45
|
-
const bidirectionalData = contourAndFindLargestBidirectional({
|
|
46
|
+
const bidirectionalData = await contourAndFindLargestBidirectional({
|
|
46
47
|
...segmentationsList.find((segmentation) => segmentation.segmentationId === segmentationId),
|
|
47
48
|
segments,
|
|
48
49
|
});
|
|
@@ -84,6 +84,9 @@ export const prepareStackDataForWorker = (segImageIds) => {
|
|
|
84
84
|
const refImageId = segImage.referencedImageId;
|
|
85
85
|
if (refImageId) {
|
|
86
86
|
const refImage = cache.getImage(refImageId);
|
|
87
|
+
if (!refImage) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
87
90
|
const refPixelData = refImage.getPixelData();
|
|
88
91
|
const refVoxelManager = refImage.voxelManager;
|
|
89
92
|
const refSpacing = [
|
|
@@ -305,8 +305,12 @@ const computeWorker = {
|
|
|
305
305
|
return bidirectionalResults;
|
|
306
306
|
},
|
|
307
307
|
generateContourSetsFromLabelmapVolume: (args) => {
|
|
308
|
-
const { segmentation, indices
|
|
309
|
-
const {
|
|
308
|
+
const { segmentation, indices } = args;
|
|
309
|
+
const { dimensions, scalarData, origin, direction, spacing } = segmentation;
|
|
310
|
+
let imageData = args.imageData;
|
|
311
|
+
if (!imageData) {
|
|
312
|
+
imageData = computeWorker.createVTKImageData(dimensions, origin, direction, spacing);
|
|
313
|
+
}
|
|
310
314
|
const numSlices = dimensions[2];
|
|
311
315
|
const pixelsPerSlice = dimensions[0] * dimensions[1];
|
|
312
316
|
const segments = computeWorker.createSegmentsFromIndices(indices);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/tools",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.5",
|
|
4
4
|
"description": "Cornerstone3D Tools",
|
|
5
5
|
"types": "./dist/esm/index.d.ts",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
"canvas": "^3.1.0"
|
|
104
104
|
},
|
|
105
105
|
"peerDependencies": {
|
|
106
|
-
"@cornerstonejs/core": "^3.8.
|
|
106
|
+
"@cornerstonejs/core": "^3.8.5",
|
|
107
107
|
"@kitware/vtk.js": "32.12.1",
|
|
108
108
|
"@types/d3-array": "^3.0.4",
|
|
109
109
|
"@types/d3-interpolate": "^3.0.1",
|
|
@@ -122,5 +122,5 @@
|
|
|
122
122
|
"type": "individual",
|
|
123
123
|
"url": "https://ohif.org/donate"
|
|
124
124
|
},
|
|
125
|
-
"gitHead": "
|
|
125
|
+
"gitHead": "782551a1523d3619fa002b9b5bb2991519fb5f40"
|
|
126
126
|
}
|