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

fix(hydration): Maintain the same slice that the user was on pre hydration in post hydration for SR and SEG. #4200

Merged
merged 3 commits into from
Jun 5, 2024
Merged
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
4 changes: 4 additions & 0 deletions extensions/cornerstone-dicom-seg/src/commandsModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const commandsModule = ({
displaySetService,
viewportGridService,
toolGroupService,
cornerstoneViewportService,
} = servicesManager.services;

const actions = {
Expand Down Expand Up @@ -210,6 +211,8 @@ const commandsModule = ({
const referencedDisplaySet = displaySetService.getDisplaySetByUID(
displaySet.referencedDisplaySetInstanceUID
);
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
const initialSliceIndex = viewport.getSliceIndex();

updateViewportsForSegmentationRendering({
viewportId,
Expand All @@ -229,6 +232,7 @@ const commandsModule = ({
segmentation.description = `S${referencedDisplaySet.SeriesNumber}: ${referencedDisplaySet.SeriesDescription}`;
return segmentationId;
},
initialSliceIndex,
});
},
/**
Expand Down
11 changes: 11 additions & 0 deletions extensions/cornerstone-dicom-seg/src/utils/hydrationUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Enums, cache } from '@cornerstonejs/core';
* @param params.loadFn - Function to load the segmentation data.
* @param params.servicesManager - The services manager.
* @param params.displaySet - the display set.
* @param params.initialSliceIndex - The initial slice index.
*
* @returns Returns true upon successful update of viewports for segmentation rendering.
*/
Expand All @@ -19,11 +20,13 @@ async function updateViewportsForSegmentationRendering({
loadFn,
servicesManager,
displaySet,
initialSliceIndex = null,
}: {
viewportId: string;
loadFn: () => Promise<string>;
servicesManager: AppTypes.ServicesManager;
displaySet?: any;
initialSliceIndex?: number;
}) {
const { cornerstoneViewportService, segmentationService, viewportGridService } =
servicesManager.services;
Expand Down Expand Up @@ -61,6 +64,14 @@ async function updateViewportsForSegmentationRendering({
};
const viewportId = viewport.viewportId;

// maintain the prehydration slice on the target viewport only
if (viewportId === targetViewportId) {
viewport.viewportOptions.initialImageOptions = {
index: initialSliceIndex,
useOnce: true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need useOnce? I don't prefer this approach.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So when the seg is hydrated, the initial image index is set, but lets say the user switches to another series, then drops the referenced series for the seg again, we should not use the initial index again, we should default to first/middle or last.

};
}

const csViewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
const prevCamera = csViewport.getCamera();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PubSubService } from '@ohif/core';
import * as OhifTypes from '@ohif/core/types';
import { Types as OhifTypes } from '@ohif/core';
import {
RenderingEngine,
StackViewport,
Expand Down Expand Up @@ -617,11 +617,9 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
imageIds?: string[]
): number {
const initialImageOptions = viewportInfo.getInitialImageOptions();

if (!initialImageOptions) {
return;
}

const { index, preset } = initialImageOptions;
const viewportType = viewportInfo.getViewportType();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { SyncGroup } from '../SyncGroupService/SyncGroupService';
export type InitialImageOptions = {
index?: number;
preset?: JumpPresets;
useOnce?: boolean;
};

export type ViewportOptions = {
Expand Down
8 changes: 4 additions & 4 deletions extensions/default/src/getHangingProtocolModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ function getHangingProtocolModule() {
name: hpMammography.id,
protocol: hpMammography,
},
// {
// name: hpScale.id,
// protocol: hpScale,
// },
{
name: hpScale.id,
protocol: hpScale,
},
Comment on lines 122 to +126
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert this for now since when you go to segmenttaion mode this gets matched for some reason

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ function TrackedMeasurementsContextProvider(

const [viewportGrid, viewportGridService] = useViewportGrid();
const { activeViewportId, viewports } = viewportGrid;
const { measurementService, displaySetService, customizationService } = servicesManager.services;
const {
measurementService,
displaySetService,
customizationService,
cornerstoneViewportService,
} = servicesManager.services;

const machineOptions = Object.assign({}, defaultOptions);
machineOptions.actions = Object.assign({}, machineOptions.actions, {
Expand Down Expand Up @@ -81,6 +86,29 @@ function TrackedMeasurementsContextProvider(
},
});
},

jumpToSameImageInActiveViewport: (ctx, evt) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this be the same logic if there is only one measurement? What I'm asking is, is jumpToSameImage = jumpToFirstMeasurement if there is only one measurement?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn’t matter how many measurements there are, it will still be the same slice the user was on

const { trackedStudy, trackedSeries, activeViewportId } = ctx;
const measurements = measurementService.getMeasurements();
const trackedMeasurements = measurements.filter(
m => trackedStudy === m.referenceStudyUID && trackedSeries.includes(m.referenceSeriesUID)
);

const trackedMeasurement = trackedMeasurements[0];
const referencedDisplaySetUID = trackedMeasurement.displaySetInstanceUID;
const viewport = cornerstoneViewportService.getCornerstoneViewport(activeViewportId);
const imageIndex = viewport.getCurrentImageIdIndex();

viewportGridService.setDisplaySetsForViewport({
viewportId: activeViewportId,
displaySetInstanceUIDs: [referencedDisplaySetUID],
viewportOptions: {
initialImageOptions: {
index: imageIndex,
},
},
});
},
showStructuredReportDisplaySetInActiveViewport: (ctx, evt) => {
if (evt.data.createdDisplaySetInstanceUIDs.length > 0) {
const StructuredReportDisplaySetInstanceUID = evt.data.createdDisplaySetInstanceUIDs[0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ const machineConfiguration = {
target: 'tracking',
actions: [
'setTrackedStudyAndMultipleSeries',
'jumpToFirstMeasurementInActiveViewport',
'jumpToSameImageInActiveViewport',
'setIsDirtyToClean',
],
cond: 'shouldHydrateStructuredReport',
Expand All @@ -274,7 +274,7 @@ const machineConfiguration = {
target: 'tracking',
actions: [
'setTrackedStudyAndMultipleSeries',
'jumpToFirstMeasurementInActiveViewport',
'jumpToSameImageInActiveViewport',
'setIsDirtyToClean',
],
},
Expand Down
8 changes: 8 additions & 0 deletions platform/ui/src/contextProviders/ViewportGridProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,14 @@ export function ViewportGridProvider({ children, service }) {

const previousViewport = viewports.get(viewportId);

// remove options that were meant for one time usage
if (previousViewport?.viewportOptions?.initialImageOptions) {
const { useOnce } = previousViewport.viewportOptions.initialImageOptions;
if (useOnce) {
previousViewport.viewportOptions.initialImageOptions = null;
}
}

// Use the newly provide viewportOptions and display set options
// when provided, and otherwise fall back to the previous ones.
// That allows for easy updates of just the display set.
Expand Down
Loading