feat(4D): Add 4D dynamic volume rendering and new pre-clinical 4d pt/ct mode (#3664)

Co-authored-by: Alireza <ar.sedghi@gmail.com>
Co-authored-by: Neil <neil.a.macphee@gmail.com>
This commit is contained in:
authored and GitHub committed 2024-04-09 23:57:34 -04:00
1 parent dc0b183dd4
commit d57e8bc157
200 files changed
+9589 -2178

No files matched your search

@@ -200,6 +200,7 @@ class CornerstoneCacheService {
volume,
volumeId,
imageIds: volumeImageIds,
isDynamicVolume: displaySet.isDynamicVolume,
});
}
@@ -228,7 +229,7 @@ class CornerstoneCacheService {
const shouldDisplaySeg = segmentationService.shouldRenderSegmentation(
viewportDisplaySetInstanceUIDs,
instance.FrameOfReferenceUID
instance?.FrameOfReferenceUID || segDisplaySet.FrameOfReferenceUID
);
if (shouldDisplaySeg) {
@@ -1289,7 +1289,7 @@ class SegmentationService extends PubSubService {
}
const { colorLUTIndex } = segmentation;
this._removeSegmentationFromCornerstone(segmentationId);
const { updatedToolGroupIds } = this._removeSegmentationFromCornerstone(segmentationId);
// Delete associated colormap
// Todo: bring this back
@@ -1309,7 +1309,9 @@ class SegmentationService extends PubSubService {
if (remainingHydratedSegmentations.length) {
const { id } = remainingHydratedSegmentations[0];
this._setActiveSegmentationForToolGroup(id, this._getApplicableToolGroupId(), false);
updatedToolGroupIds.forEach(toolGroupId => {
this._setActiveSegmentationForToolGroup(id, toolGroupId, false);
});
}
}
@@ -1966,6 +1968,7 @@ class SegmentationService extends PubSubService {
const removeFromCache = true;
const segmentationState = cstSegmentation.state;
const sourceSegState = segmentationState.getSegmentation(segmentationId);
const updatedToolGroupIds: Set<string> = new Set();
if (!sourceSegState) {
return;
@@ -1981,6 +1984,7 @@ class SegmentationService extends PubSubService {
segmentationRepresentations.forEach(representation => {
if (representation.segmentationId === segmentationId) {
UIDsToRemove.push(representation.segmentationRepresentationUID);
updatedToolGroupIds.add(toolGroupId);
}
});
@@ -1998,6 +2002,8 @@ class SegmentationService extends PubSubService {
if (removeFromCache && cache.getVolumeLoadObject(segmentationId)) {
cache.removeVolumeLoadObject(segmentationId);
}
return { updatedToolGroupIds: Array.from(updatedToolGroupIds) };
}
private _updateCornerstoneSegmentations({ segmentationId, notYetUpdatedAtSource }) {
@@ -1,4 +1,5 @@
import { ToolGroupManager, Enums, Types } from '@cornerstonejs/tools';
import { eventTarget } from '@cornerstonejs/core';
import { Types as OhifTypes, pubSubServiceInterface } from '@ohif/core';
import getActiveViewportEnabledElement from '../../utils/getActiveViewportEnabledElement';
@@ -6,6 +7,8 @@ import getActiveViewportEnabledElement from '../../utils/getActiveViewportEnable
const EVENTS = {
VIEWPORT_ADDED: 'event::cornerstone::toolgroupservice:viewportadded',
TOOLGROUP_CREATED: 'event::cornerstone::toolgroupservice:toolgroupcreated',
TOOL_ACTIVATED: 'event::cornerstone::toolgroupservice:toolactivated',
PRIMARY_TOOL_ACTIVATED: 'event::cornerstone::toolgroupservice:primarytoolactivated',
};
type Tool = {
@@ -38,18 +41,26 @@ export default class ToolGroupService {
EVENTS: { [key: string]: string };
constructor(serviceManager) {
const { cornerstoneViewportService, viewportGridService } = serviceManager.services;
const { cornerstoneViewportService, viewportGridService, uiNotificationService } =
serviceManager.services;
this.cornerstoneViewportService = cornerstoneViewportService;
this.viewportGridService = viewportGridService;
this.uiNotificationService = uiNotificationService;
this.listeners = {};
this.EVENTS = EVENTS;
Object.assign(this, pubSubServiceInterface);
this._init();
}
onModeExit() {
this.destroy();
}
private _init() {
eventTarget.addEventListener(Enums.Events.TOOL_ACTIVATED, this._onToolActivated);
}
/**
* Retrieves a tool group from the ToolGroupManager by tool group ID.
* If no tool group ID is provided, it retrieves the tool group of the active viewport.
@@ -105,12 +116,14 @@ export default class ToolGroupService {
return toolGroup.getActivePrimaryMouseButtonTool();
}
public destroy() {
public destroy(): void {
ToolGroupManager.destroy();
this.toolGroupIds = new Set();
eventTarget.removeEventListener(Enums.Events.TOOL_ACTIVATED, this._onToolActivated);
}
public destroyToolGroup(toolGroupId: string) {
public destroyToolGroup(toolGroupId: string): void {
ToolGroupManager.destroyToolGroup(toolGroupId);
this.toolGroupIds.delete(toolGroupId);
}
@@ -222,6 +235,10 @@ export default class ToolGroupService {
toolInstance.configuration = config;
}
public getActivePrimaryMouseButtonTool(toolGroupId?: string): string {
return this.getToolGroup(toolGroupId)?.getActivePrimaryMouseButtonTool();
}
private _setToolsMode(toolGroup, tools) {
const { active, passive, enabled, disabled } = tools;
@@ -279,4 +296,23 @@ export default class ToolGroupService {
addTools(tools.disabled);
}
}
private _onToolActivated = (evt: Types.EventTypes.ToolActivatedEventType) => {
const { toolGroupId, toolName, toolBindingsOptions } = evt.detail;
const isPrimaryTool = toolBindingsOptions.bindings?.some(
binding => binding.mouseButton === Enums.MouseBindings.Primary
);
const callbackProps = {
toolGroupId,
toolName,
toolBindingsOptions,
};
this._broadcastEvent(EVENTS.TOOL_ACTIVATED, callbackProps);
if (isPrimaryTool) {
this._broadcastEvent(EVENTS.PRIMARY_TOOL_ACTIVATED, callbackProps);
}
};
}
@@ -24,6 +24,7 @@ import JumpPresets from '../../utils/JumpPresets';
const EVENTS = {
VIEWPORT_DATA_CHANGED: 'event::cornerstoneViewportService:viewportDataChanged',
VIEWPORT_VOLUMES_CHANGED: 'event::cornerstoneViewportService:viewportVolumesChanged',
};
/**
@@ -793,6 +794,10 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
}
viewport.render();
this._broadcastEvent(this.EVENTS.VIEWPORT_VOLUMES_CHANGED, {
viewportInfo,
});
}
private _addSegmentationRepresentationToToolGroupIfNecessary(