ohif-viewer/extensions/cornerstone/src/services/SyncGroupService/createHydrateSegmentationSynchronizer.ts
Alireza 6dd150d401
fix: ohif tests to run with cornerstone 3d 5.0 (#6043)
* chore(tests): Update multiple screenshot test images for various specs

* feat(screenshot-reviewer): Add screenshot review tool and update package.json scripts

* fix(DICOMSRDisplayTool): Improve actor presence check in viewport

* chore(tests): Update multiple screenshot assets for various specs

* chore(tests): Integrate waitForPaintToSettle and waitForViewportsRendered in multiple specs for improved rendering stability

* chore(tests): Update screenshot assets for SEGHydration and SEGNoHydration specs

* test: update progressive loading screenshots

* jest 30 test fixes for compatibility with pnpm cs3d

* Use correct setDisplaySets instead of setDataId

* fix: Naming change for LegacyVolumeViewport3D

* Update to allow tolerance for contour tests

* update

* fix

* refactor: Replace instanceof checks with utility functions for viewport type validation

* fix: Update createSegmentationForViewport to handle undefined displaySetInstanceUID gracefully

* bun lock

* fix: Install cs3d with pnpm instead of bun

* Update node version for playwright

* Update to v5.0.0 of cs3d

* fix: Build dependency

* audit

* Change to a web await retry assert

* Fix timing related test failures

* fix: Freehand close

---------

Co-authored-by: Bill Wallace <wayfarer3130@gmail.com>
2026-06-09 20:25:14 -04:00

114 lines
3.9 KiB
TypeScript

import { Enums as CoreEnums, Types, getEnabledElementByViewportId } from '@cornerstonejs/core';
import {
SynchronizerManager,
Synchronizer,
Enums,
Types as ToolsTypes,
} from '@cornerstonejs/tools';
import { isAnyDisplaySetCommon } from '../../utils/isAnyDisplaySetCommon';
import { isVolume3DViewportType } from '../../utils/getLegacyViewportType';
const { createSynchronizer } = SynchronizerManager;
const { SEGMENTATION_REPRESENTATION_MODIFIED } = Enums.Events;
const { BlendModes } = CoreEnums;
export default function createHydrateSegmentationSynchronizer(
synchronizerName: string,
{ servicesManager, ...options }: { servicesManager: AppTypes.ServicesManager; options }
): Synchronizer {
const stackImageSynchronizer = createSynchronizer(
synchronizerName,
SEGMENTATION_REPRESENTATION_MODIFIED,
(synchronizerInstance, sourceViewport, targetViewport, sourceEvent) => {
return segmentationRepresentationModifiedCallback(
synchronizerInstance,
sourceViewport,
targetViewport,
sourceEvent,
{ servicesManager, options }
);
},
{
eventSource: 'eventTarget',
}
);
return stackImageSynchronizer;
}
/**
* This method will add the segmentation representation to any target viewports having:
*
* 1. the same FrameOfReferenceUID (FOR) as the segmentation representation, or
* 2. a shared DisplaySet with the source viewport when no FOR is present.
*/
const segmentationRepresentationModifiedCallback = async (
synchronizerInstance: Synchronizer,
sourceViewport: Types.IViewportId,
targetViewport: Types.IViewportId,
sourceEvent: Event,
{ servicesManager, options }: { servicesManager: AppTypes.ServicesManager; options: unknown }
) => {
const event = sourceEvent as ToolsTypes.EventTypes.SegmentationRepresentationModifiedEventType;
const { segmentationId, type: segmentationRepresentationType } = event.detail;
const { segmentationService, cornerstoneViewportService } = servicesManager.services;
const targetViewportId = targetViewport.viewportId;
const sourceViewportId = sourceViewport.viewportId;
const { viewport } = getEnabledElementByViewportId(targetViewportId);
const sourceViewportInfo = cornerstoneViewportService.getViewportInfo(sourceViewportId);
const targetViewportInfo = cornerstoneViewportService.getViewportInfo(targetViewportId);
const sourceDisplaySetUIDs = extractDisplaySetUIDs(sourceViewportInfo);
const targetDisplaySetUIDs = extractDisplaySetUIDs(targetViewportInfo);
const sharedDisplaySetExists = isAnyDisplaySetCommon(sourceDisplaySetUIDs, targetDisplaySetUIDs);
const targetFrameOfReferenceUID = viewport.getFrameOfReferenceUID();
const sourceFrameOfReferenceUID =
getEnabledElementByViewportId(sourceViewportId)?.viewport?.getFrameOfReferenceUID();
if (!sharedDisplaySetExists && !targetFrameOfReferenceUID) {
return;
}
if (!sharedDisplaySetExists && targetFrameOfReferenceUID !== sourceFrameOfReferenceUID) {
return;
}
const targetViewportRepresentation = segmentationService.getSegmentationRepresentations(
targetViewportId,
{ segmentationId }
);
if (targetViewportRepresentation.length > 0) {
return;
}
// Ensure the segmentation representation aligns with the target viewport type.
const type: Enums.SegmentationRepresentations =
isVolume3DViewportType(viewport)
? Enums.SegmentationRepresentations.Surface
: ((segmentationRepresentationType as Enums.SegmentationRepresentations) ??
Enums.SegmentationRepresentations.Labelmap);
await segmentationService.addSegmentationRepresentation(targetViewportId, {
segmentationId,
type,
config: {
blendMode:
viewport?.getBlendMode?.() === 1 ? BlendModes.LABELMAP_EDGE_PROJECTION_BLEND : undefined,
},
});
};
/**
* Extracts the displaySetInstanceUIDs from a viewportInfo.
*/
function extractDisplaySetUIDs(viewportInfo) {
return viewportInfo.getViewportData().data.map(ds => ds.displaySetInstanceUID);
}