* 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>
114 lines
3.9 KiB
TypeScript
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);
|
|
}
|