Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(variationTool): Variation Tool to perform deformation operations on drawn contours #1499

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions common/reviews/api/tools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -6366,6 +6366,69 @@ declare namespace utilities {
}
export { utilities }

// @public (undocumented)
export class VariationTool extends BaseTool {
constructor(toolProps?: PublicToolProps, defaultToolProps?: ToolProps);
// (undocumented)
_activateDraw: (element: HTMLDivElement) => void;
// (undocumented)
_calculateCursor(element: any, centerCanvas?: any): void;
// (undocumented)
createHoverData(element: any, centerCanvas: any): {
brushCursor: {
metadata: {
viewPlaneNormal: Types_2.Point3;
viewUp: Types_2.Point3;
FrameOfReferenceUID: string;
referencedImageId: string;
toolName: string;
segmentColor: Types_2.Color;
};
data: {};
};
centerCanvas: any;
segmentIndex: number;
segmentationId: string;
segmentationRepresentationUID: string;
segmentColor: Types_2.Color;
viewportIdsToRender: string[];
};
// (undocumented)
_deactivateDraw: (element: HTMLDivElement) => void;
// (undocumented)
_dragCallback: (evt: EventTypes_2.InteractionEventType) => void;
// (undocumented)
editData: {
segmentationId: string;
planeContours: any;
viewport: Types_2.IVolumeViewport | Types_2.IStackViewport;
} | null;
// (undocumented)
_endCallback: (evt: EventTypes_2.InteractionEventType) => void;
// (undocumented)
getSegmentationId(): string;
// (undocumented)
invalidateCursor(): void;
// (undocumented)
mouseMoveCallback: (evt: EventTypes_2.InteractionEventType) => void;
// (undocumented)
onSetToolDisabled: () => void;
// (undocumented)
onSetToolEnabled: () => void;
// (undocumented)
onSetToolPassive: () => void;
// (undocumented)
preMouseDownCallback: (evt: EventTypes_2.MouseDownActivateEventType) => boolean;
// (undocumented)
renderAnnotation(enabledElement: Types_2.IEnabledElement, svgDrawingHelper: SVGDrawingHelper): void;
// (undocumented)
static toolName: string;
// (undocumented)
_triggerAnnotationRender(viewport: Types_2.IStackViewport | Types_2.IVolumeViewport): void;
// (undocumented)
updateCursor(evt: EventTypes_2.InteractionEventType): void;
}

declare namespace vec2 {
export {
findClosestPoint,
Expand Down
215 changes: 215 additions & 0 deletions packages/tools/examples/variationTool/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
import {
Enums,
geometryLoader,
RenderingEngine,
setVolumesForViewports,
Types,
volumeLoader,
} from '@cornerstonejs/core';
import * as cornerstoneTools from '@cornerstonejs/tools';
import {
createImageIdsAndCacheMetaData,
initDemo,
setTitleAndDescription,
} from '../../../../utils/demo/helpers';
import assetsURL from '../../../../utils/assets/assetsURL.json';

// This is for debugging purposes
console.warn(
'Click on index.ts to open source code for this example --------->'
);

const {
SegmentationDisplayTool,
ToolGroupManager,
Enums: csToolsEnums,
segmentation,
ZoomTool,
PanTool,
StackScrollMouseWheelTool,
TrackballRotateTool,
VariationTool,
} = cornerstoneTools;
const { MouseBindings } = csToolsEnums;
const { ViewportType, GeometryType } = Enums;

// Define a unique id for the volume
const volumeName = 'CT_VOLUME_ID'; // Id of the volume less loader prefix
const volumeLoaderScheme = 'cornerstoneStreamingImageVolume'; // Loader id which defines which volume loader to use
const volumeId = `${volumeLoaderScheme}:${volumeName}`; // VolumeId with loader id + volume id
const segmentationId = 'MY_SEGMENTATION_ID';
const toolGroupId = 'MY_TOOLGROUP_ID';

// disable fill
cornerstoneTools.segmentation.state.getGlobalConfig().representations.CONTOUR.renderFill =
false;

// ======== Set up page ======== //
setTitleAndDescription(
'Variation Tool',
'Here we demonstrate how to perform deformation operations on drawn contours'
);

const size = '500px';
const content = document.getElementById('content');
const viewportGrid = document.createElement('div');

viewportGrid.style.display = 'flex';
viewportGrid.style.display = 'flex';
viewportGrid.style.flexDirection = 'row';

const element1 = document.createElement('div');
element1.oncontextmenu = () => false;

element1.style.width = size;
element1.style.height = size;

viewportGrid.appendChild(element1);

content.appendChild(viewportGrid);

const instructions = document.createElement('p');
content.append(instructions);

async function addSegmentationsToState() {
const circle = await fetch(assetsURL.CircleContour).then((res) => res.json());

// load the contour data
const geometryIds = [];

const promises = circle.contourSets.map((contourSet) => {
const geometryId = contourSet.id;
geometryIds.push(geometryId);
return geometryLoader.createAndCacheGeometry(geometryId, {
type: GeometryType.CONTOUR,
geometryData: contourSet as Types.PublicContourSetData,
});
});

await Promise.all(promises);

// Add the segmentations to state
segmentation.addSegmentations([
{
segmentationId: `${segmentationId}`,
representation: {
// The type of segmentation
type: csToolsEnums.SegmentationRepresentations.Contour,
// The actual segmentation data, in the case of contour geometry
// this is a reference to the geometry data
data: {
geometryIds: geometryIds,
},
},
},
]);
}

/**
* Runs the demo
*/
async function run() {
// Init Cornerstone and related libraries
await initDemo();

// Add tools to Cornerstone3D
cornerstoneTools.addTool(SegmentationDisplayTool);
cornerstoneTools.addTool(PanTool);
cornerstoneTools.addTool(ZoomTool);
cornerstoneTools.addTool(StackScrollMouseWheelTool);
cornerstoneTools.addTool(TrackballRotateTool);
cornerstoneTools.addTool(VariationTool);

// Define tool groups to add the segmentation display tool to
const toolGroup = ToolGroupManager.createToolGroup(toolGroupId);

toolGroup.addTool(SegmentationDisplayTool.toolName);
toolGroup.addTool(PanTool.toolName);
toolGroup.addTool(ZoomTool.toolName);
toolGroup.addTool(StackScrollMouseWheelTool.toolName);
toolGroup.addTool(VariationTool.toolName);
toolGroup.setToolEnabled(SegmentationDisplayTool.toolName);

toolGroup.setToolActive(PanTool.toolName, {
bindings: [
{
mouseButton: MouseBindings.Auxiliary, // Middle Click
},
],
});
toolGroup.setToolActive(ZoomTool.toolName, {
bindings: [
{
mouseButton: MouseBindings.Secondary, // Right Click
},
],
});

toolGroup.setToolActive(StackScrollMouseWheelTool.toolName);
toolGroup.setToolActive(VariationTool.toolName, {
bindings: [
{
mouseButton: MouseBindings.Primary, // Left Click
},
],
});

// Get Cornerstone imageIds for the source data and fetch metadata into RAM
const imageIds = await createImageIdsAndCacheMetaData({
StudyInstanceUID:
'1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463',
SeriesInstanceUID:
'1.3.6.1.4.1.14519.5.2.1.7009.2403.226151125820845824875394858561',
wadoRsRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb',
});

// Define a volume in memory
const volume = await volumeLoader.createAndCacheVolume(volumeId, {
imageIds,
});

// Add some segmentations based on the source data volume
await addSegmentationsToState();

// Instantiate a rendering engine
const renderingEngineId = 'myRenderingEngine';
const renderingEngine = new RenderingEngine(renderingEngineId);

// Create the viewports
const viewportId1 = 'CT_AXIAL';

const viewportInputArray = [
{
viewportId: viewportId1,
type: ViewportType.ORTHOGRAPHIC,
element: element1,
defaultOptions: {
orientation: Enums.OrientationAxis.AXIAL,
background: <Types.Point3>[0.2, 0, 0.2],
},
},
];

renderingEngine.setViewports(viewportInputArray);

toolGroup.addViewport(viewportId1, renderingEngineId);

// Set the volume to load
volume.load();

// Set volumes on the viewports
setVolumesForViewports(renderingEngine, [{ volumeId }], [viewportId1]);

// // Add the segmentation representation to the toolgroup
await segmentation.addSegmentationRepresentations(toolGroupId, [
{
segmentationId: `${segmentationId}`,
type: csToolsEnums.SegmentationRepresentations.Contour,
},
]);

// Render the image
renderingEngine.render();
}

run();
2 changes: 2 additions & 0 deletions packages/tools/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import {
SculptorTool,
SegmentSelectTool,
WindowLevelRegionTool,
VariationTool,
} from './tools';

import VideoRedactionTool from './tools/annotation/VideoRedactionTool';
Expand Down Expand Up @@ -147,6 +148,7 @@ export {
BrushTool,
OrientationMarkerTool,
SegmentSelectTool,
VariationTool,
// Synchronizers
synchronizers,
Synchronizer,
Expand Down
Loading