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: added promise lifecycle to Viewport and hook for HangingProtocol #3352

Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ const OHIFCornerstoneViewport = React.memo(props => {
servicesManager,
onElementEnabled,
onElementDisabled,
onViewportDataLoad,
// Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation
// of the imageData in the OHIFCornerstoneViewport. This prop is used
// to set the initial state of the viewport's first image to render
Expand Down Expand Up @@ -433,7 +434,11 @@ const OHIFCornerstoneViewport = React.memo(props => {
viewportOptions,
displaySetOptions,
presentations
);
).then((val) => {
if (onViewportDataLoad) {
onViewportDataLoad(val)
}
});;

if (measurement) {
cs3DTools.annotation.selection.setAnnotationSelected(measurement.uid);
Expand Down Expand Up @@ -723,6 +728,7 @@ OHIFCornerstoneViewport.propTypes = {
displaySetOptions: PropTypes.arrayOf(PropTypes.any),
servicesManager: PropTypes.object.isRequired,
onElementEnabled: PropTypes.func,
onViewportDataLoad: PropTypes.func,
// Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation
// of the imageData in the OHIFCornerstoneViewport. This prop is used
// to set the initial state of the viewport's first image to render
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ const EVENTS = {
* Handles cornerstone viewport logic including enabling, disabling, and
* updating the viewport.
*/
class CornerstoneViewportService extends PubSubService
implements IViewportService {
class CornerstoneViewportService
extends PubSubService
implements IViewportService
{
static REGISTRATION = {
name: 'cornerstoneViewportService',
altName: 'CornerstoneViewportService',
Expand Down Expand Up @@ -238,7 +240,7 @@ class CornerstoneViewportService extends PubSubService
publicViewportOptions: PublicViewportOptions,
publicDisplaySetOptions: DisplaySetOptions[],
presentations?: Presentations
): void {
): Promise<void> {
const renderingEngine = this.getRenderingEngine();
const viewportId =
publicViewportOptions.viewportId || this.getViewportId(viewportIndex);
Expand All @@ -261,14 +263,12 @@ class CornerstoneViewportService extends PubSubService

viewportInfo.setRenderingEngineId(renderingEngine.id);

const {
viewportOptions,
displaySetOptions,
} = this._getViewportAndDisplaySetOptions(
publicViewportOptions,
publicDisplaySetOptions,
viewportInfo
);
const { viewportOptions, displaySetOptions } =
this._getViewportAndDisplaySetOptions(
publicViewportOptions,
publicDisplaySetOptions,
viewportInfo
);

viewportInfo.setViewportOptions(viewportOptions);
viewportInfo.setDisplaySetOptions(displaySetOptions);
Expand Down Expand Up @@ -296,7 +296,12 @@ class CornerstoneViewportService extends PubSubService
renderingEngine.enableElement(viewportInput);

const viewport = renderingEngine.getViewport(viewportId);
this._setDisplaySets(viewport, viewportData, viewportInfo, presentations);
const displaySetPromsie = this._setDisplaySets(
viewport,
viewportData,
viewportInfo,
presentations
);

// The broadcast event here ensures that listeners have a valid, up to date
// viewport to access. Doing it too early can result in exceptions or
Expand All @@ -306,6 +311,8 @@ class CornerstoneViewportService extends PubSubService
viewportIndex,
viewportId,
});

return displaySetPromsie;
}

public getCornerstoneViewport(
Expand Down Expand Up @@ -370,14 +377,11 @@ class CornerstoneViewportService extends PubSubService
viewportData: StackViewportData,
viewportInfo: ViewportInfo,
presentations: Presentations
): void {
): Promise<void> {
const displaySetOptions = viewportInfo.getDisplaySetOptions();

const {
imageIds,
initialImageIndex,
displaySetInstanceUID,
} = viewportData.data;
const { imageIds, initialImageIndex, displaySetInstanceUID } =
viewportData.data;

this.viewportsDisplaySets.set(viewport.id, [displaySetInstanceUID]);

Expand Down Expand Up @@ -409,7 +413,7 @@ class CornerstoneViewportService extends PubSubService
}
}

viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
return viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
viewport.setProperties(properties);
const camera = presentations.positionPresentation?.camera;
if (camera) viewport.setCamera(camera);
Expand All @@ -436,9 +440,8 @@ class CornerstoneViewportService extends PubSubService
const viewport = this.getCornerstoneViewport(
viewportInfo.getViewportId()
);
const imageSliceData = csUtils.getImageSliceDataForVolumeViewport(
viewport
);
const imageSliceData =
csUtils.getImageSliceDataForVolumeViewport(viewport);

if (!imageSliceData) {
return;
Expand Down Expand Up @@ -571,11 +574,9 @@ class CornerstoneViewportService extends PubSubService
viewport,
volumeInputArray,
presentations
) {
const {
displaySetService,
toolGroupService,
} = this.servicesManager.services;
): Promise<void> {
const { displaySetService, toolGroupService } =
this.servicesManager.services;

await viewport.setVolumes(volumeInputArray);
this.setPresentations(viewport, presentations);
Expand Down Expand Up @@ -621,10 +622,8 @@ class CornerstoneViewportService extends PubSubService
displaySetInstanceUIDs: string[],
viewport: any
) {
const {
segmentationService,
toolGroupService,
} = this.servicesManager.services;
const { segmentationService, toolGroupService } =
this.servicesManager.services;

const toolGroup = toolGroupService.getToolGroupForViewport(viewport.id);

Expand All @@ -639,9 +638,10 @@ class CornerstoneViewportService extends PubSubService

// if there is already a segmentation representation for this segmentation
// for this toolGroup, don't bother at all
const isSegmentationInToolGroup = toolGroupSegmentationRepresentations.find(
representation => representation.segmentationId === segmentation.id
);
const isSegmentationInToolGroup =
toolGroupSegmentationRepresentations.find(
representation => representation.segmentationId === segmentation.id
);

if (isSegmentationInToolGroup) {
continue;
Expand Down Expand Up @@ -684,10 +684,8 @@ class CornerstoneViewportService extends PubSubService
displaySet: any,
viewport: any
) {
const {
segmentationService,
toolGroupService,
} = this.servicesManager.services;
const { segmentationService, toolGroupService } =
this.servicesManager.services;

const { referencedVolumeId } = displaySet;
const segmentationId = displaySet.displaySetInstanceUID;
Expand All @@ -713,27 +711,26 @@ class CornerstoneViewportService extends PubSubService
viewportIndex: number,
viewportData,
keepCamera = false
) {
): Promise<void> {
const viewportInfo = this.getViewportInfoByIndex(viewportIndex);

const viewportId = viewportInfo.getViewportId();
const viewport = this.getCornerstoneViewport(viewportId);
const viewportCamera = viewport.getCamera();

if (viewport instanceof VolumeViewport) {
this._setVolumeViewport(viewport, viewportData, viewportInfo).then(() => {
if (keepCamera) {
viewport.setCamera(viewportCamera);
viewport.render();
return this._setVolumeViewport(viewport, viewportData, viewportInfo).then(
() => {
if (keepCamera) {
viewport.setCamera(viewportCamera);
viewport.render();
}
}
});

return;
);
}

if (viewport instanceof StackViewport) {
this._setStackViewport(viewport, viewportData, viewportInfo);
return;
return this._setStackViewport(viewport, viewportData, viewportInfo);
}
}

Expand Down Expand Up @@ -786,9 +783,9 @@ class CornerstoneViewportService extends PubSubService
viewportData: StackViewportData | VolumeViewportData,
viewportInfo: ViewportInfo,
presentations: Presentations = {}
): void {
): Promise<void> {
if (viewport instanceof StackViewport) {
this._setStackViewport(
return this._setStackViewport(
viewport,
viewportData as StackViewportData,
viewportInfo,
Expand All @@ -798,7 +795,7 @@ class CornerstoneViewportService extends PubSubService
viewport instanceof VolumeViewport ||
viewport instanceof VolumeViewport3D
) {
this._setVolumeViewport(
return this._setVolumeViewport(
viewport,
viewportData as VolumeViewportData,
viewportInfo,
Expand Down
7 changes: 7 additions & 0 deletions platform/core/src/types/HangingProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,13 @@ export type ProtocolNotifications = {
// The numRows and numCols is included in the command params, so it is possible
// to apply a specific hanging protocol
onLayoutChange?: Command[];

// Once all image data containers are loaded, this command runs.
// While the data container exists, the actual internal data may not be
// hydrated. This is because stack and volume viewports will load progressively.
// TODO: Another protocol notification which may need to load is when all data is actually
// loaded. This may be related to imageLoader code.
onLayoutViewportDataContainersLoaded?: Command[];
};

/**
Expand Down
13 changes: 13 additions & 0 deletions platform/viewer/src/components/ViewportGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ViewportGrid, ViewportPane, useViewportGrid } from '@ohif/ui';
import { utils } from '@ohif/core';
import EmptyViewport from './EmptyViewport';
import classNames from 'classnames';
import { commandsManager } from '../App';

const { isEqualWithin } = utils;

Expand Down Expand Up @@ -260,6 +261,17 @@ function ViewerViewportGrid(props) {
const viewportPanes = [];

const numViewportPanes = viewportGridService.getNumViewportPanes();
let readyViewports = 0;
const checkReady = () => {
readyViewports = readyViewports + 1;
if (readyViewports === numViewportPanes) {
const layoutLoaded = hangingProtocolService?.protocol?.callbacks?.onLayoutViewportDataContainersLoaded;
if (layoutLoaded) {
commandsManager.run(layoutLoaded)
}
}
}

for (let i = 0; i < numViewportPanes; i++) {
const viewportIndex = i;
const isActive = activeViewportIndex === viewportIndex;
Expand Down Expand Up @@ -344,6 +356,7 @@ function ViewerViewportGrid(props) {
viewportOptions={viewportOptions}
displaySetOptions={displaySetOptions}
needsRerendering={displaySetsNeedsRerendering}
onViewportDataLoad={checkReady}
/>
</div>
</ViewportPane>
Expand Down