feat(segmentation mode): Add create, and export SEG with Brushes (#3632)

This commit is contained in:
Alireza authored and GitHub committed 2023-09-22 10:23:44 -04:00
1 parent 896866e9d0
commit 48bbd6281a
186 files changed
+6801 -2883

No files matched your search

@@ -18,7 +18,6 @@ import toggleStackImageSync from './utils/stackSync/toggleStackImageSync';
import { getFirstAnnotationSelected } from './utils/measurementServiceMappings/utils/selection';
import getActiveViewportEnabledElement from './utils/getActiveViewportEnabledElement';
import { CornerstoneServices } from './types';
import ImageOverlayViewerTool from './tools/ImageOverlayViewerTool';
function commandsModule({
servicesManager,
@@ -266,7 +265,6 @@ function commandsModule({
toolbarServiceRecordInteraction: props => {
toolbarService.recordInteraction(props);
},
setToolActive: ({ toolName, toolGroupId = null, toggledState }) => {
if (toolName === 'Crosshairs') {
const activeViewportToolGroup = toolGroupService.getToolGroup(null);
@@ -13,12 +13,12 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
const handleCineClose = () => {
toolbarService.recordInteraction({
groupId: 'MoreTools',
itemId: 'cine',
interactionType: 'toggle',
commands: [
{
commandName: 'toggleCine',
commandOptions: {},
toolName: 'cine',
context: 'CORNERSTONE',
},
],
+1 -1
View File
@@ -137,7 +137,7 @@ const cornerstoneExtension: Types.Extensions.Extension = {
export type { PublicViewportOptions };
export {
measurementMappingUtils,
CornerstoneExtensionTypes,
CornerstoneExtensionTypes as Types,
toolNames,
getActiveViewportEnabledElement,
};
+14 -1
View File
@@ -18,6 +18,7 @@ const DEFAULT_CONTEXT_MENU_CLICKS = {
{
commandName: 'showCornerstoneContextMenu',
commandOptions: {
requireNearbyToolData: true,
menuId: 'measurementsContextMenu',
},
},
@@ -62,8 +63,20 @@ function initContextMenu({
const customizations =
customizationService.get('cornerstoneViewportClickCommands') || DEFAULT_CONTEXT_MENU_CLICKS;
const toRun = customizations[name];
if (!toRun) {
return;
}
// only find nearbyToolData if required, for the click (which closes the context menu
// we don't need to find nearbyToolData)
let nearbyToolData = null;
if (toRun.commands.some(command => command.commandOptions?.requireNearbyToolData)) {
nearbyToolData = findNearbyToolData(commandsManager, evt);
}
const options = {
nearbyToolData: findNearbyToolData(commandsManager, evt),
nearbyToolData,
event: evt,
};
commandsManager.run(toRun, options);
@@ -25,6 +25,9 @@ import {
annotation,
ReferenceLinesTool,
TrackballRotateTool,
CircleScissorsTool,
RectangleScissorsTool,
SphereScissorsTool,
} from '@cornerstonejs/tools';
import CalibrationLineTool from './tools/CalibrationLineTool';
@@ -59,6 +62,9 @@ export default function initCornerstoneTools(configuration = {}) {
addTool(ReferenceLinesTool);
addTool(CalibrationLineTool);
addTool(TrackballRotateTool);
addTool(CircleScissorsTool);
addTool(RectangleScissorsTool);
addTool(SphereScissorsTool);
addTool(ImageOverlayViewerTool);
// Modify annotation tools to use dashed lines on SR
@@ -101,6 +107,9 @@ const toolNames = {
ReferenceLines: ReferenceLinesTool.toolName,
CalibrationLine: CalibrationLineTool.toolName,
TrackballRotateTool: TrackballRotateTool.toolName,
CircleScissors: CircleScissorsTool.toolName,
RectangleScissors: RectangleScissorsTool.toolName,
SphereScissors: SphereScissorsTool.toolName,
ImageOverlayViewer: ImageOverlayViewerTool.toolName,
};
@@ -210,7 +210,7 @@ class CornerstoneCacheService {
}
private _shouldRenderSegmentation(displaySets) {
const { segmentationService } = this.servicesManager.services;
const { segmentationService, displaySetService } = this.servicesManager.services;
const viewportDisplaySetInstanceUIDs = displaySets.map(
({ displaySetInstanceUID }) => displaySetInstanceUID
@@ -222,10 +222,11 @@ class CornerstoneCacheService {
for (const segmentation of segmentations) {
const segDisplaySetInstanceUID = segmentation.displaySetInstanceUID;
const segDisplaySet = displaySetService.getDisplaySetByUID(segDisplaySetInstanceUID);
const shouldDisplaySeg = segmentationService.shouldRenderSegmentation(
viewportDisplaySetInstanceUIDs,
segDisplaySetInstanceUID
segDisplaySet.instances[0].FrameOfReferenceUID
);
if (shouldDisplaySeg) {
@@ -99,43 +99,51 @@ class SegmentationService extends PubSubService {
};
/**
* It adds a segment to a segmentation, basically just setting the properties for
* the segment.
* @param segmentationId - The ID of the segmentation you want to add a
* segment to.
* @param segmentIndex - The index of the segment to add.
* @param properties - The properties of the segment to add including
* -- label: the label of the segment
* -- color: the color of the segment
* -- opacity: the opacity of the segment
* -- visibility: the visibility of the segment (boolean)
* -- isLocked: whether the segment is locked for editing
* -- active: whether the segment is currently the active segment to be edited
* Adds a new segment to the specified segmentation.
* @param segmentationId - The ID of the segmentation to add the segment to.
* @param config - An object containing the configuration options for the new segment.
* - segmentIndex: (optional) The index of the segment to add. If not provided, the next available index will be used.
* - toolGroupId: (optional) The ID of the tool group to associate the new segment with. If not provided, the first available tool group will be used.
* - properties: (optional) An object containing the properties of the new segment.
* - label: (optional) The label of the new segment. If not provided, a default label will be used.
* - color: (optional) The color of the new segment in RGB format. If not provided, a default color will be used.
* - opacity: (optional) The opacity of the new segment. If not provided, a default opacity will be used.
* - visibility: (optional) Whether the new segment should be visible. If not provided, the segment will be visible by default.
* - isLocked: (optional) Whether the new segment should be locked for editing. If not provided, the segment will not be locked by default.
* - active: (optional) Whether the new segment should be the active segment to be edited. If not provided, the segment will not be active by default.
*/
public addSegment(
segmentationId: string,
segmentIndex: number,
toolGroupId?: string,
properties?: {
label?: string;
color?: ohifTypes.RGB;
opacity?: number;
visibility?: boolean;
isLocked?: boolean;
active?: boolean;
}
config: {
segmentIndex?: number;
toolGroupId?: string;
properties?: {
label?: string;
color?: ohifTypes.RGB;
opacity?: number;
visibility?: boolean;
isLocked?: boolean;
active?: boolean;
};
} = {}
): void {
if (segmentIndex === 0) {
if (config?.segmentIndex === 0) {
throw new Error('Segment index 0 is reserved for "no label"');
}
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
const toolGroupId = config.toolGroupId ?? this._getFirstToolGroupId();
const { segmentationRepresentationUID, segmentation } = this._getSegmentationInfo(
segmentationId,
toolGroupId
);
let segmentIndex = config.segmentIndex;
if (!segmentIndex) {
// grab the next available segment index
segmentIndex = segmentation.segments.length === 0 ? 1 : segmentation.segments.length;
}
if (this._getSegmentInfo(segmentation, segmentIndex)) {
throw new Error(`Segment ${segmentIndex} already exists`);
}
@@ -147,7 +155,7 @@ class SegmentationService extends PubSubService {
);
segmentation.segments[segmentIndex] = {
label: properties.label,
label: config.properties?.label ?? `Segment ${segmentIndex}`,
segmentIndex: segmentIndex,
color: [rgbaColor[0], rgbaColor[1], rgbaColor[2]],
opacity: rgbaColor[3],
@@ -157,9 +165,12 @@ class SegmentationService extends PubSubService {
segmentation.segmentCount++;
// make the newly added segment the active segment
this._setActiveSegment(segmentationId, segmentIndex);
const suppressEvents = true;
if (properties !== undefined) {
const { color: newColor, opacity, isLocked, visibility, active } = properties;
if (config.properties !== undefined) {
const { color: newColor, opacity, isLocked, visibility, active } = config.properties;
if (newColor !== undefined) {
this._setSegmentColor(segmentationId, segmentIndex, newColor, toolGroupId, suppressEvents);
@@ -281,17 +292,21 @@ class SegmentationService extends PubSubService {
);
}
public setSegmentLockedForSegmentation(
segmentationId: string,
segmentIndex: number,
isLocked: boolean
): void {
public setSegmentLocked(segmentationId: string, segmentIndex: number, isLocked: boolean): void {
const suppressEvents = false;
this._setSegmentLocked(segmentationId, segmentIndex, isLocked, suppressEvents);
}
public setSegmentLabel(segmentationId: string, segmentIndex: number, segmentLabel: string): void {
this._setSegmentLabel(segmentationId, segmentIndex, segmentLabel);
/**
* Toggles the locked state of a segment in a segmentation.
* @param segmentationId - The ID of the segmentation.
* @param segmentIndex - The index of the segment to toggle.
*/
public toggleSegmentLocked(segmentationId: string, segmentIndex: number): void {
const segmentation = this.getSegmentation(segmentationId);
const segment = this._getSegmentInfo(segmentation, segmentIndex);
const isLocked = !segment.isLocked;
this._setSegmentLocked(segmentationId, segmentIndex, isLocked);
}
public setSegmentColor(
@@ -353,7 +368,7 @@ class SegmentationService extends PubSubService {
this._setActiveSegmentationForToolGroup(segmentationId, toolGroupId, suppressEvents);
}
public setActiveSegmentForSegmentation(segmentationId: string, segmentIndex: number): void {
public setActiveSegment(segmentationId: string, segmentIndex: number): void {
this._setActiveSegment(segmentationId, segmentIndex, false);
}
@@ -434,12 +449,14 @@ class SegmentationService extends PubSubService {
},
]);
// Define a new color LUT and associate it with this segmentation.
// Todo: need to be generalized to accept custom color LUTs
const newColorLUT = this.generateNewColorLUT();
const newColorLUTIndex = this.getNextColorLUTIndex();
cstSegmentation.config.color.addColorLUT(newColorLUT, newColorLUTIndex);
// if first segmentation, we can use the default colorLUT, otherwise
// we need to generate a new one and use a new colorLUT
const colorLUTIndex = 0;
if (Object.keys(this.segmentations).length !== 0) {
const newColorLUT = this.generateNewColorLUT();
const colorLUTIndex = this.getNextColorLUTIndex();
cstSegmentation.config.color.addColorLUT(newColorLUT, colorLUTIndex);
}
this.segmentations[segmentationId] = {
...segmentation,
@@ -448,8 +465,8 @@ class SegmentationService extends PubSubService {
activeSegmentIndex: segmentation.activeSegmentIndex ?? null,
segmentCount: segmentation.segmentCount ?? 0,
isActive: false,
colorLUTIndex: newColorLUTIndex,
isVisible: true,
colorLUTIndex,
};
cachedSegmentation = this.segmentations[segmentationId];
@@ -736,6 +753,97 @@ class SegmentationService extends PubSubService {
return this.addOrUpdateSegmentation(segmentation, suppressEvents);
}
// Todo: this should not run on the main thread
public calculateCentroids = (
segmentationId: string,
segmentIndex?: number
): Map<number, { x: number; y: number; z: number; world: number[] }> => {
const segmentation = this.getSegmentation(segmentationId);
const volume = this.getLabelmapVolume(segmentationId);
const { dimensions, imageData } = volume;
const scalarData = volume.getScalarData();
const [dimX, dimY, numFrames] = dimensions;
const frameLength = dimX * dimY;
const segmentIndices = segmentIndex
? [segmentIndex]
: segmentation.segments
.filter(segment => segment?.segmentIndex)
.map(segment => segment.segmentIndex);
const segmentIndicesSet = new Set(segmentIndices);
const centroids = new Map();
for (const index of segmentIndicesSet) {
centroids.set(index, { x: 0, y: 0, z: 0, count: 0 });
}
let voxelIndex = 0;
for (let frame = 0; frame < numFrames; frame++) {
for (let p = 0; p < frameLength; p++) {
const segmentIndex = scalarData[voxelIndex++];
if (segmentIndicesSet.has(segmentIndex)) {
const centroid = centroids.get(segmentIndex);
centroid.x += p % dimX;
centroid.y += (p / dimX) | 0;
centroid.z += frame;
centroid.count++;
}
}
}
const result = new Map();
for (const [index, centroid] of centroids) {
const count = centroid.count;
const normalizedCentroid = {
x: centroid.x / count,
y: centroid.y / count,
z: centroid.z / count,
};
normalizedCentroid.world = imageData.indexToWorld([
normalizedCentroid.x,
normalizedCentroid.y,
normalizedCentroid.z,
]);
result.set(index, normalizedCentroid);
}
this.setCentroids(segmentationId, result);
return result;
};
private setCentroids = (
segmentationId: string,
centroids: Map<number, { image: number[]; world?: number[] }>
): void => {
const segmentation = this.getSegmentation(segmentationId);
const imageData = this.getLabelmapVolume(segmentationId).imageData; // Assuming this method returns imageData
if (!segmentation.cachedStats) {
segmentation.cachedStats = { segmentCenter: {} };
} else if (!segmentation.cachedStats.segmentCenter) {
segmentation.cachedStats.segmentCenter = {};
}
for (const [segmentIndex, centroid] of centroids) {
let world = centroid.world;
// If world coordinates are not provided, calculate them
if (!world || world.length === 0) {
world = imageData.indexToWorld(centroid.image);
}
segmentation.cachedStats.segmentCenter[segmentIndex] = {
center: {
image: centroid.image,
world: world,
},
};
}
this.addOrUpdateSegmentation(segmentation, true, true);
};
public jumpToSegmentCenter(
segmentationId: string,
segmentIndex: number,
@@ -749,6 +857,10 @@ class SegmentationService extends PubSubService {
const { toolGroupService } = this.servicesManager.services;
const center = this._getSegmentCenter(segmentationId, segmentIndex);
if (!center?.world) {
return;
}
const { world } = center;
// todo: generalize
@@ -831,6 +943,7 @@ class SegmentationService extends PubSubService {
displaySetInstanceUID: string,
options?: {
segmentationId: string;
FrameOfReferenceUID: string;
label: string;
}
): Promise<string> => {
@@ -865,6 +978,8 @@ class SegmentationService extends PubSubService {
// We should set it as active by default, as it created for display
isActive: true,
type: representationType,
FrameOfReferenceUID:
options?.FrameOfReferenceUID || displaySet.instances?.[0]?.FrameOfReferenceUID,
representationData: {
LABELMAP: {
volumeId: segmentationId,
@@ -892,7 +1007,8 @@ class SegmentationService extends PubSubService {
toolGroupId: string,
segmentationId: string,
hydrateSegmentation = false,
representationType = csToolsEnums.SegmentationRepresentations.Labelmap
representationType = csToolsEnums.SegmentationRepresentations.Labelmap,
suppressEvents = false
): Promise<void> => {
const segmentation = this.getSegmentation(segmentationId);
@@ -959,13 +1075,19 @@ class SegmentationService extends PubSubService {
);
}
if (isLocked !== undefined) {
if (isLocked) {
this._setSegmentLocked(segmentationId, segmentIndex, isLocked, suppressEvents);
}
}
if (!suppressEvents) {
this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {
segmentation,
});
}
};
public setSegmentRGBAColorForSegmentation = (
public setSegmentRGBAColor = (
segmentationId: string,
segmentIndex: number,
rgbaColor,
@@ -1008,11 +1130,11 @@ class SegmentationService extends PubSubService {
if (!segmentation) {
throw new Error(`Segmentation with segmentationId ${segmentationId} not found.`);
}
this._setDisplaySetIsHydrated(segmentationId, true);
segmentation.hydrated = true;
// Not all segmentations have dipslaysets, some of them are derived in the client
this._setDisplaySetIsHydrated(segmentationId, true);
if (!suppressEvents) {
this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {
segmentation,
@@ -1021,8 +1143,13 @@ class SegmentationService extends PubSubService {
};
private _setDisplaySetIsHydrated(displaySetUID: string, isHydrated: boolean): void {
const { DisplaySetService: displaySetService } = this.servicesManager.services;
const { displaySetService } = this.servicesManager.services;
const displaySet = displaySetService.getDisplaySetByUID(displaySetUID);
if (!displaySet) {
return;
}
displaySet.isHydrated = isHydrated;
displaySetService.setDisplaySetMetadataInvalidated(displaySetUID, false);
}
@@ -1167,7 +1294,6 @@ class SegmentationService extends PubSubService {
}
const { colorLUTIndex } = segmentation;
this._removeSegmentationFromCornerstone(segmentationId);
// Delete associated colormap
@@ -1181,8 +1307,12 @@ class SegmentationService extends PubSubService {
if (wasActive) {
const remainingSegmentations = this._getSegmentations();
if (remainingSegmentations.length) {
const { id } = remainingSegmentations[0];
const remainingHydratedSegmentations = remainingSegmentations.filter(
segmentation => segmentation.hydrated
);
if (remainingHydratedSegmentations.length) {
const { id } = remainingHydratedSegmentations[0];
this._setActiveSegmentationForToolGroup(id, this._getFirstToolGroupId(), false);
}
@@ -1312,15 +1442,11 @@ class SegmentationService extends PubSubService {
return cstSegmentation.state.getSegmentationRepresentations(toolGroupId);
};
public setSegmentLabelForSegmentation(
segmentationId: string,
segmentIndex: number,
label: string
) {
this._setSegmentLabelForSegmentation(segmentationId, segmentIndex, label);
public setSegmentLabel(segmentationId: string, segmentIndex: number, label: string) {
this._setSegmentLabel(segmentationId, segmentIndex, label);
}
private _setSegmentLabelForSegmentation(
private _setSegmentLabel(
segmentationId: string,
segmentIndex: number,
label: string,
@@ -1348,8 +1474,8 @@ class SegmentationService extends PubSubService {
}
}
public shouldRenderSegmentation(viewportDisplaySetInstanceUIDs, segDisplaySetInstanceUID) {
if (!viewportDisplaySetInstanceUIDs || !viewportDisplaySetInstanceUIDs.length) {
public shouldRenderSegmentation(viewportDisplaySetInstanceUIDs, segmentationFrameOfReferenceUID) {
if (!viewportDisplaySetInstanceUIDs?.length) {
return false;
}
@@ -1357,10 +1483,6 @@ class SegmentationService extends PubSubService {
let shouldDisplaySeg = false;
const segDisplaySet = displaySetService.getDisplaySetByUID(segDisplaySetInstanceUID);
const segFrameOfReferenceUID = this._getFrameOfReferenceUIDForSeg(segDisplaySet);
// check if the displaySet is sharing the same frameOfReferenceUID
// with the new segmentation
for (const displaySetInstanceUID of viewportDisplaySetInstanceUIDs) {
@@ -1370,7 +1492,7 @@ class SegmentationService extends PubSubService {
// don't want to show the segmentation for all the frames
if (
displaySet.isReconstructable &&
displaySet?.images?.[0]?.FrameOfReferenceUID === segFrameOfReferenceUID
displaySet?.images?.[0]?.FrameOfReferenceUID === segmentationFrameOfReferenceUID
) {
shouldDisplaySeg = true;
break;
@@ -1717,7 +1839,7 @@ class SegmentationService extends PubSubService {
const segmentationRepresentations =
this.getSegmentationRepresentationsForToolGroup(toolGroupId);
if (segmentationRepresentations.length === 0) {
if (!segmentationRepresentations?.length) {
return;
}
@@ -39,6 +39,8 @@ type Segmentation = {
isActive: boolean;
// if the segmentation is visible in the viewer
isVisible: boolean;
// the frame of reference UID of the segmentation
FrameOfReferenceUID: string;
// the label of the segmentation
label: string;
// the number of segments in the segmentation
@@ -97,9 +97,9 @@ export default class ToolGroupService {
}
public getActiveToolForViewport(viewportId: string): string {
const toolGroup = ToolGroupManager.getToolGroupForViewport(viewportId);
const toolGroup = this.getToolGroupForViewport(viewportId);
if (!toolGroup) {
return null;
return;
}
return toolGroup.getActivePrimaryMouseButtonTool();
@@ -184,13 +184,9 @@ export default class ToolGroupService {
this._setToolsMode(toolGroup, tools);
}
public createToolGroupAndAddTools(
toolGroupId: string,
tools: Array<Tool>,
configs: any = {}
): Types.IToolGroup {
public createToolGroupAndAddTools(toolGroupId: string, tools: Array<Tool>): Types.IToolGroup {
const toolGroup = this.createToolGroup(toolGroupId);
this.addToolsToToolGroup(toolGroupId, tools, configs);
this.addToolsToToolGroup(toolGroupId, tools);
return toolGroup;
}
@@ -239,34 +235,6 @@ export default class ToolGroupService {
toolInstance.configuration = config;
}
private _getToolNames(toolGroupTools: Tools): string[] {
const toolNames = [];
if (toolGroupTools.active) {
toolGroupTools.active.forEach(tool => {
toolNames.push(tool.toolName);
});
}
if (toolGroupTools.passive) {
toolGroupTools.passive.forEach(tool => {
toolNames.push(tool.toolName);
});
}
if (toolGroupTools.enabled) {
toolGroupTools.enabled.forEach(tool => {
toolNames.push(tool.toolName);
});
}
if (toolGroupTools.disabled) {
toolGroupTools.disabled.forEach(tool => {
toolNames.push(tool.toolName);
});
}
return toolNames;
}
private _setToolsMode(toolGroup, tools) {
const { active, passive, enabled, disabled } = tools;
@@ -295,17 +263,33 @@ export default class ToolGroupService {
}
}
private _addTools(toolGroup, tools, configs) {
const toolNames = this._getToolNames(tools);
toolNames.forEach(toolName => {
// Initialize the toolConfig if no configuration is provided
const toolConfig = configs[toolName] ?? {};
private _addTools(toolGroup, tools) {
const addTools = tools => {
tools.forEach(({ toolName, parentTool, configuration }) => {
if (parentTool) {
toolGroup.addToolInstance(toolName, parentTool, {
...configuration,
});
} else {
toolGroup.addTool(toolName, { ...configuration });
}
});
};
// if (volumeUID) {
// toolConfig.volumeUID = volumeUID;
// }
if (tools.active) {
addTools(tools.active);
}
toolGroup.addTool(toolName, { ...toolConfig });
});
if (tools.passive) {
addTools(tools.passive);
}
if (tools.enabled) {
addTools(tools.enabled);
}
if (tools.disabled) {
addTools(tools.disabled);
}
}
}
@@ -15,11 +15,7 @@ import {
import { utilities as csToolsUtils, Enums as csToolsEnums } from '@cornerstonejs/tools';
import { IViewportService } from './IViewportService';
import { RENDERING_ENGINE_ID } from './constants';
import ViewportInfo, {
ViewportOptions,
DisplaySetOptions,
PublicViewportOptions,
} from './Viewport';
import ViewportInfo, { DisplaySetOptions, PublicViewportOptions } from './Viewport';
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
import { Presentation, Presentations } from '../../types/Presentation';
@@ -586,10 +582,23 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
continue;
}
// otherwise, check if the hydrated segmentations are in the same FOR
// otherwise, check if the hydrated segmentations are in the same FrameOfReferenceUID
// as the primary displaySet, if so add the representation (since it was not there)
const { id: segDisplaySetInstanceUID, type } = segmentation;
const segFrameOfReferenceUID = this._getFrameOfReferenceUID(segDisplaySetInstanceUID);
const { id: segDisplaySetInstanceUID } = segmentation;
let segFrameOfReferenceUID = this._getFrameOfReferenceUID(segDisplaySetInstanceUID);
if (!segFrameOfReferenceUID) {
// if the segmentation displaySet does not have a FrameOfReferenceUID, we might check the
// segmentation itself maybe it has a FrameOfReferenceUID
const { FrameOfReferenceUID } = segmentation;
if (FrameOfReferenceUID) {
segFrameOfReferenceUID = FrameOfReferenceUID;
}
}
if (!segFrameOfReferenceUID) {
return;
}
let shouldDisplaySeg = false;
@@ -1,5 +1,6 @@
import { metaData } from '@cornerstonejs/core';
import { VolumeViewport, metaData } from '@cornerstonejs/core';
import { utilities } from '@cornerstonejs/core';
import { IStackViewport, IVolumeViewport, Point3 } from '@cornerstonejs/core/dist/esm/types';
import { AnnotationDisplayTool, drawing } from '@cornerstonejs/tools';
import { guid } from '@ohif/core/src/utils';
@@ -46,6 +47,15 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
this._cachedOverlayMetadata = new Map();
};
protected getReferencedImageId(viewport: IStackViewport | IVolumeViewport): string {
if (viewport instanceof VolumeViewport) {
return;
}
const targetId = this.getTargetId(viewport);
return targetId.split('imageId:')[1];
}
renderAnnotation = (enabledElement, svgDrawingHelper) => {
const { viewport } = enabledElement;
@@ -97,7 +97,7 @@ class DicomLoaderService {
if (
(!imageInstance && !nonImageInstance) ||
!nonImageInstance.imageId.startsWith('dicomfile')
!nonImageInstance.imageId?.startsWith('dicomfile')
) {
return;
}