fix(rt): dont convert to volume for RTSTRUCT (#4157)
Co-authored-by: Alireza <ar.sedghi@gmail.com>
This commit is contained in:
parent
b0af8ec553
commit
7745c092bb
@ -111,7 +111,7 @@ function OHIFCornerstoneRTViewport(props: withAppTypes) {
|
|||||||
{...props}
|
{...props}
|
||||||
displaySets={[referencedDisplaySet, rtDisplaySet]}
|
displaySets={[referencedDisplaySet, rtDisplaySet]}
|
||||||
viewportOptions={{
|
viewportOptions={{
|
||||||
viewportType: 'volume',
|
viewportType: 'stack',
|
||||||
toolGroupId: toolGroupId,
|
toolGroupId: toolGroupId,
|
||||||
orientation: viewportOptions.orientation,
|
orientation: viewportOptions.orientation,
|
||||||
viewportId: viewportOptions.viewportId,
|
viewportId: viewportOptions.viewportId,
|
||||||
|
|||||||
@ -213,7 +213,7 @@ const commandsModule = ({
|
|||||||
updateViewportsForSegmentationRendering({
|
updateViewportsForSegmentationRendering({
|
||||||
viewportId,
|
viewportId,
|
||||||
servicesManager,
|
servicesManager,
|
||||||
referencedDisplaySetInstanceUID: displaySet.referencedDisplaySetInstanceUID,
|
displaySet,
|
||||||
loadFn: async () => {
|
loadFn: async () => {
|
||||||
const segDisplaySet = displaySet;
|
const segDisplaySet = displaySet;
|
||||||
const suppressEvents = false;
|
const suppressEvents = false;
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { Enums, cache } from '@cornerstonejs/core';
|
|||||||
* @param params.viewportId - ID of the viewport to be updated.
|
* @param params.viewportId - ID of the viewport to be updated.
|
||||||
* @param params.loadFn - Function to load the segmentation data.
|
* @param params.loadFn - Function to load the segmentation data.
|
||||||
* @param params.servicesManager - The services manager.
|
* @param params.servicesManager - The services manager.
|
||||||
* @param params.referencedDisplaySetInstanceUID - Optional UID for the referenced display set instance.
|
* @param params.displaySet - the display set.
|
||||||
*
|
*
|
||||||
* @returns Returns true upon successful update of viewports for segmentation rendering.
|
* @returns Returns true upon successful update of viewports for segmentation rendering.
|
||||||
*/
|
*/
|
||||||
@ -18,12 +18,12 @@ async function updateViewportsForSegmentationRendering({
|
|||||||
viewportId,
|
viewportId,
|
||||||
loadFn,
|
loadFn,
|
||||||
servicesManager,
|
servicesManager,
|
||||||
referencedDisplaySetInstanceUID,
|
displaySet,
|
||||||
}: {
|
}: {
|
||||||
viewportId: string;
|
viewportId: string;
|
||||||
loadFn: () => Promise<string>;
|
loadFn: () => Promise<string>;
|
||||||
servicesManager: AppTypes.ServicesManager;
|
servicesManager: AppTypes.ServicesManager;
|
||||||
referencedDisplaySetInstanceUID?: string;
|
displaySet?: any;
|
||||||
}) {
|
}) {
|
||||||
const { cornerstoneViewportService, segmentationService, viewportGridService } =
|
const { cornerstoneViewportService, segmentationService, viewportGridService } =
|
||||||
servicesManager.services;
|
servicesManager.services;
|
||||||
@ -31,13 +31,13 @@ async function updateViewportsForSegmentationRendering({
|
|||||||
const viewport = getTargetViewport({ viewportId, viewportGridService });
|
const viewport = getTargetViewport({ viewportId, viewportGridService });
|
||||||
const targetViewportId = viewport.viewportOptions.viewportId;
|
const targetViewportId = viewport.viewportOptions.viewportId;
|
||||||
|
|
||||||
referencedDisplaySetInstanceUID =
|
const referencedDisplaySetInstanceUID =
|
||||||
referencedDisplaySetInstanceUID || viewport?.displaySetInstanceUIDs[0];
|
displaySet?.referencedDisplaySetInstanceUID || viewport?.displaySetInstanceUIDs[0];
|
||||||
|
|
||||||
const updatedViewports = getUpdatedViewportsForSegmentation({
|
const updatedViewports = getUpdatedViewportsForSegmentation({
|
||||||
servicesManager,
|
servicesManager,
|
||||||
viewportId,
|
viewportId,
|
||||||
referencedDisplaySetInstanceUID,
|
displaySet,
|
||||||
});
|
});
|
||||||
|
|
||||||
// create Segmentation callback which needs to be waited until
|
// create Segmentation callback which needs to be waited until
|
||||||
@ -56,7 +56,7 @@ async function updateViewportsForSegmentationRendering({
|
|||||||
updatedViewports.forEach(async viewport => {
|
updatedViewports.forEach(async viewport => {
|
||||||
viewport.viewportOptions = {
|
viewport.viewportOptions = {
|
||||||
...viewport.viewportOptions,
|
...viewport.viewportOptions,
|
||||||
viewportType: 'volume',
|
viewportType: displaySet?.Modality === 'RTSTRUCT' ? 'stack' : 'volume',
|
||||||
needsRerendering: true,
|
needsRerendering: true,
|
||||||
};
|
};
|
||||||
const viewportId = viewport.viewportId;
|
const viewportId = viewport.viewportId;
|
||||||
@ -66,7 +66,7 @@ async function updateViewportsForSegmentationRendering({
|
|||||||
|
|
||||||
// only run the createSegmentationForVolume for the targetViewportId
|
// only run the createSegmentationForVolume for the targetViewportId
|
||||||
// since the rest will get handled by cornerstoneViewportService
|
// since the rest will get handled by cornerstoneViewportService
|
||||||
if (volumeExists && viewportId === targetViewportId) {
|
if ((volumeExists || displaySet.Modality === 'RTSTRUCT') && viewportId === targetViewportId) {
|
||||||
await createSegmentationForVolume();
|
await createSegmentationForVolume();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -126,14 +126,14 @@ const getTargetViewport = ({ viewportId, viewportGridService }) => {
|
|||||||
* @param {Object} params - Parameters for the function.
|
* @param {Object} params - Parameters for the function.
|
||||||
* @param params.viewportId - the ID of the viewport to be updated.
|
* @param params.viewportId - the ID of the viewport to be updated.
|
||||||
* @param params.servicesManager - The services manager
|
* @param params.servicesManager - The services manager
|
||||||
* @param params.referencedDisplaySetInstanceUID - Optional UID for the referenced display set instance.
|
* @param params.displaySet - the display set.
|
||||||
*
|
*
|
||||||
* @returns {Array} Returns an array of viewports that require updates for segmentation rendering.
|
* @returns {Array} Returns an array of viewports that require updates for segmentation rendering.
|
||||||
*/
|
*/
|
||||||
function getUpdatedViewportsForSegmentation({
|
function getUpdatedViewportsForSegmentation({
|
||||||
viewportId,
|
viewportId,
|
||||||
servicesManager,
|
servicesManager,
|
||||||
referencedDisplaySetInstanceUID,
|
displaySet,
|
||||||
}: withAppTypes) {
|
}: withAppTypes) {
|
||||||
const { hangingProtocolService, displaySetService, segmentationService, viewportGridService } =
|
const { hangingProtocolService, displaySetService, segmentationService, viewportGridService } =
|
||||||
servicesManager.services;
|
servicesManager.services;
|
||||||
@ -146,7 +146,7 @@ function getUpdatedViewportsForSegmentation({
|
|||||||
const displaySetInstanceUIDs = viewports.get(targetViewportId).displaySetInstanceUIDs;
|
const displaySetInstanceUIDs = viewports.get(targetViewportId).displaySetInstanceUIDs;
|
||||||
|
|
||||||
const referenceDisplaySetInstanceUID =
|
const referenceDisplaySetInstanceUID =
|
||||||
referencedDisplaySetInstanceUID || displaySetInstanceUIDs[0];
|
displaySet?.referencedDisplaySetInstanceUID || displaySetInstanceUIDs[0];
|
||||||
|
|
||||||
const referencedDisplaySet = displaySetService.getDisplaySetByUID(referenceDisplaySetInstanceUID);
|
const referencedDisplaySet = displaySetService.getDisplaySetByUID(referenceDisplaySetInstanceUID);
|
||||||
const segmentationFrameOfReferenceUID = referencedDisplaySet.instances[0].FrameOfReferenceUID;
|
const segmentationFrameOfReferenceUID = referencedDisplaySet.instances[0].FrameOfReferenceUID;
|
||||||
@ -175,7 +175,7 @@ function getUpdatedViewportsForSegmentation({
|
|||||||
viewportId,
|
viewportId,
|
||||||
displaySetInstanceUIDs: viewport.displaySetInstanceUIDs,
|
displaySetInstanceUIDs: viewport.displaySetInstanceUIDs,
|
||||||
viewportOptions: {
|
viewportOptions: {
|
||||||
viewportType: 'volume',
|
viewportType: displaySet.Modality === 'RTSTRUCT' ? 'stack' : 'volume',
|
||||||
needsRerendering: true,
|
needsRerendering: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -305,7 +305,7 @@ function CustomizableViewportOverlay({
|
|||||||
function _getViewportInstances(viewportData) {
|
function _getViewportInstances(viewportData) {
|
||||||
const imageIds = [];
|
const imageIds = [];
|
||||||
if (viewportData.viewportType === Enums.ViewportType.STACK) {
|
if (viewportData.viewportType === Enums.ViewportType.STACK) {
|
||||||
imageIds.push(viewportData.data.imageIds[0]);
|
imageIds.push(viewportData.data[0].imageIds[0]);
|
||||||
} else if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC) {
|
} else if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC) {
|
||||||
const volumes = viewportData.data;
|
const volumes = viewportData.data;
|
||||||
volumes.forEach(volume => {
|
volumes.forEach(volume => {
|
||||||
@ -345,7 +345,7 @@ const getInstanceNumber = (viewportData, viewportId, imageIndex, cornerstoneView
|
|||||||
};
|
};
|
||||||
|
|
||||||
function _getInstanceNumberFromStack(viewportData, imageIndex) {
|
function _getInstanceNumberFromStack(viewportData, imageIndex) {
|
||||||
const imageIds = viewportData.data.imageIds;
|
const imageIds = viewportData.data[0].imageIds;
|
||||||
const imageId = imageIds[imageIndex];
|
const imageId = imageIds[imageIndex];
|
||||||
|
|
||||||
if (!imageId) {
|
if (!imageId) {
|
||||||
|
|||||||
@ -48,7 +48,7 @@ function CornerstoneImageScrollbar({
|
|||||||
|
|
||||||
setImageSliceData({
|
setImageSliceData({
|
||||||
imageIndex: imageIndex,
|
imageIndex: imageIndex,
|
||||||
numberOfSlices: viewportData.data.imageIds.length,
|
numberOfSlices: viewportData.data[0].imageIds.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -78,7 +78,7 @@ function CornerstoneImageScrollbar({
|
|||||||
// find the index of imageId in the imageIds
|
// find the index of imageId in the imageIds
|
||||||
setImageSliceData({
|
setImageSliceData({
|
||||||
imageIndex: newImageIdIndex,
|
imageIndex: newImageIdIndex,
|
||||||
numberOfSlices: viewportData.data.imageIds.length,
|
numberOfSlices: viewportData.data[0].imageIds.length,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -67,7 +67,7 @@ function ViewportOrientationMarkers({
|
|||||||
let rowCosines, columnCosines;
|
let rowCosines, columnCosines;
|
||||||
if (viewportData.viewportType === 'stack') {
|
if (viewportData.viewportType === 'stack') {
|
||||||
const imageIndex = imageSliceData.imageIndex;
|
const imageIndex = imageSliceData.imageIndex;
|
||||||
const imageId = viewportData.data.imageIds?.[imageIndex];
|
const imageId = viewportData.data[0].imageIds?.[imageIndex];
|
||||||
|
|
||||||
// Workaround for below TODO stub
|
// Workaround for below TODO stub
|
||||||
if (!imageId) {
|
if (!imageId) {
|
||||||
|
|||||||
@ -143,14 +143,25 @@ class CornerstoneCacheService {
|
|||||||
return newViewportData;
|
return newViewportData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getStackViewportData(
|
private async _getStackViewportData(
|
||||||
dataSource,
|
dataSource,
|
||||||
displaySets,
|
displaySets,
|
||||||
initialImageIndex,
|
initialImageIndex,
|
||||||
viewportType: Enums.ViewportType
|
viewportType: Enums.ViewportType
|
||||||
): StackViewportData {
|
): Promise<StackViewportData> {
|
||||||
// For Stack Viewport we don't have fusion currently
|
const overlayDisplaySets = displaySets.filter(ds => ds.isOverlayDisplaySet);
|
||||||
const displaySet = displaySets[0];
|
const nonOverlayDisplaySets = displaySets.filter(ds => !ds.isOverlayDisplaySet);
|
||||||
|
|
||||||
|
// load overlays if they are not loaded
|
||||||
|
for (const overlayDisplaySet of overlayDisplaySets) {
|
||||||
|
if (overlayDisplaySet.load && overlayDisplaySet.load instanceof Function) {
|
||||||
|
const { userAuthenticationService } = this.servicesManager.services;
|
||||||
|
const headers = userAuthenticationService.getAuthorizationHeader();
|
||||||
|
await overlayDisplaySet.load({ headers });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const displaySet = nonOverlayDisplaySets[0];
|
||||||
|
|
||||||
let stackImageIds = this.stackImageIds.get(displaySet.displaySetInstanceUID);
|
let stackImageIds = this.stackImageIds.get(displaySet.displaySetInstanceUID);
|
||||||
|
|
||||||
@ -159,23 +170,23 @@ class CornerstoneCacheService {
|
|||||||
this.stackImageIds.set(displaySet.displaySetInstanceUID, stackImageIds);
|
this.stackImageIds.set(displaySet.displaySetInstanceUID, stackImageIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { displaySetInstanceUID, StudyInstanceUID, isCompositeStack } = displaySet;
|
// Ensuring the first non-overlay `displaySet` is always the primary one
|
||||||
|
const StackViewportData = [displaySet, ...overlayDisplaySets].map(ds => {
|
||||||
|
const { displaySetInstanceUID, StudyInstanceUID, isCompositeStack } = ds;
|
||||||
|
|
||||||
const StackViewportData: StackViewportData = {
|
return {
|
||||||
viewportType,
|
|
||||||
data: {
|
|
||||||
StudyInstanceUID,
|
StudyInstanceUID,
|
||||||
displaySetInstanceUID,
|
displaySetInstanceUID,
|
||||||
isCompositeStack,
|
isCompositeStack,
|
||||||
imageIds: stackImageIds,
|
imageIds: stackImageIds,
|
||||||
},
|
initialImageIndex,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
viewportType,
|
||||||
|
data: StackViewportData,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof initialImageIndex === 'number') {
|
|
||||||
StackViewportData.data.initialImageIndex = initialImageIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
return StackViewportData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _getVolumeViewportData(
|
private async _getVolumeViewportData(
|
||||||
|
|||||||
@ -557,9 +557,14 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const displaySetOptions = viewportInfo.getDisplaySetOptions();
|
const displaySetOptions = viewportInfo.getDisplaySetOptions();
|
||||||
|
|
||||||
const { imageIds, initialImageIndex, displaySetInstanceUID } = viewportData.data;
|
const displaySetInstanceUIDs = viewportData.data.map(data => data.displaySetInstanceUID);
|
||||||
|
|
||||||
this.viewportsDisplaySets.set(viewport.id, [displaySetInstanceUID]);
|
// based on the cache service construct always the first one is the non-overlay
|
||||||
|
// and the rest are overlays
|
||||||
|
|
||||||
|
this.viewportsDisplaySets.set(viewport.id, [...displaySetInstanceUIDs]);
|
||||||
|
|
||||||
|
const { initialImageIndex, imageIds } = viewportData.data[0];
|
||||||
|
|
||||||
let initialImageIndexToUse =
|
let initialImageIndexToUse =
|
||||||
presentations?.positionPresentation?.initialImageIndex ?? initialImageIndex;
|
presentations?.positionPresentation?.initialImageIndex ?? initialImageIndex;
|
||||||
@ -588,6 +593,8 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._handleOverlays(viewport);
|
||||||
|
|
||||||
return viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
|
return viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
|
||||||
viewport.setProperties({ ...properties });
|
viewport.setProperties({ ...properties });
|
||||||
this.setPresentations(viewport.id, presentations);
|
this.setPresentations(viewport.id, presentations);
|
||||||
@ -772,24 +779,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
|||||||
|
|
||||||
this.setPresentations(viewport.id, presentations);
|
this.setPresentations(viewport.id, presentations);
|
||||||
|
|
||||||
// load any secondary displaySets
|
this._handleOverlays(viewport);
|
||||||
const displaySetInstanceUIDs = this.viewportsDisplaySets.get(viewport.id);
|
|
||||||
|
|
||||||
// can be SEG or RTSTRUCT for now
|
|
||||||
const overlayDisplaySet = displaySetInstanceUIDs
|
|
||||||
.map(displaySetService.getDisplaySetByUID)
|
|
||||||
.find(displaySet => displaySet?.isOverlayDisplaySet);
|
|
||||||
|
|
||||||
if (overlayDisplaySet) {
|
|
||||||
this.addOverlayRepresentationForDisplaySet(overlayDisplaySet, viewport);
|
|
||||||
} else {
|
|
||||||
// If the displaySet is not a SEG displaySet we assume it is a primary displaySet
|
|
||||||
// and we can look into hydrated segmentations to check if any of them are
|
|
||||||
// associated with the primary displaySet
|
|
||||||
|
|
||||||
// get segmentations only returns the hydrated segmentations
|
|
||||||
this._addSegmentationRepresentationToToolGroupIfNecessary(displaySetInstanceUIDs, viewport);
|
|
||||||
}
|
|
||||||
|
|
||||||
const toolGroup = toolGroupService.getToolGroupForViewport(viewport.id);
|
const toolGroup = toolGroupService.getToolGroupForViewport(viewport.id);
|
||||||
csToolsUtils.segmentation.triggerSegmentationRender(toolGroup.id);
|
csToolsUtils.segmentation.triggerSegmentationRender(toolGroup.id);
|
||||||
@ -809,6 +799,28 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _handleOverlays(viewport: Types.IStackViewport | Types.IVolumeViewport) {
|
||||||
|
const { displaySetService } = this.servicesManager.services;
|
||||||
|
|
||||||
|
// load any secondary displaySets
|
||||||
|
const displaySetInstanceUIDs = this.viewportsDisplaySets.get(viewport.id);
|
||||||
|
|
||||||
|
// can be SEG or RTSTRUCT for now
|
||||||
|
const overlayDisplaySet = displaySetInstanceUIDs
|
||||||
|
.map(displaySetService.getDisplaySetByUID)
|
||||||
|
.find(displaySet => displaySet?.isOverlayDisplaySet);
|
||||||
|
if (overlayDisplaySet) {
|
||||||
|
this.addOverlayRepresentationForDisplaySet(overlayDisplaySet, viewport);
|
||||||
|
} else {
|
||||||
|
// If the displaySet is not a SEG displaySet we assume it is a primary displaySet
|
||||||
|
// and we can look into hydrated segmentations to check if any of them are
|
||||||
|
// associated with the primary displaySet
|
||||||
|
|
||||||
|
// get segmentations only returns the hydrated segmentations
|
||||||
|
this._addSegmentationRepresentationToToolGroupIfNecessary(displaySetInstanceUIDs, viewport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _addSegmentationRepresentationToToolGroupIfNecessary(
|
private _addSegmentationRepresentationToToolGroupIfNecessary(
|
||||||
displaySetInstanceUIDs: string[],
|
displaySetInstanceUIDs: string[],
|
||||||
viewport: any
|
viewport: any
|
||||||
|
|||||||
@ -22,7 +22,7 @@ type VolumeData = {
|
|||||||
|
|
||||||
type StackViewportData = {
|
type StackViewportData = {
|
||||||
viewportType: Enums.ViewportType;
|
viewportType: Enums.ViewportType;
|
||||||
data: StackData;
|
data: StackData[];
|
||||||
};
|
};
|
||||||
|
|
||||||
type VolumeViewportData = {
|
type VolumeViewportData = {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user