{"version":3,"file":"82.bundle.22e2c1bf0ebdaddc04c4.js","mappings":"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","sources":["webpack:///../../../extensions/cornerstone/src/initWADOImageLoader.js","webpack:///../../../extensions/cornerstone/src/utils/callInputDialog.tsx","webpack:///../../../extensions/cornerstone/src/utils/getActiveViewportEnabledElement.ts","webpack:///../../../extensions/cornerstone/src/tools/CalibrationLineTool.ts","webpack:///../../../extensions/cornerstone/src/tools/ImageOverlayViewerTool.tsx","webpack:///../../../extensions/cornerstone/src/initCornerstoneTools.js","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/constants/supportedTools.js","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/Length.ts","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/utils/getHandlesFromPoints.js","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/utils/selection.ts","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/utils/getDisplayUnit.js","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/Bidirectional.ts","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/EllipticalROI.ts","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/CircleROI.ts","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/ArrowAnnotate.ts","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/CobbAngle.ts","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/Angle.ts","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/PlanarFreehandROI.ts","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/RectangleROI.ts","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/measurementServiceMappingsFactory.ts","webpack:///../../../extensions/cornerstone/src/initMeasurementService.js","webpack:///../../../extensions/cornerstone/src/initCineService.ts","webpack:///../../../extensions/cornerstone/src/utils/interleaveCenterLoader.ts","webpack:///../../../extensions/cornerstone/src/utils/getInterleavedFrames.js","webpack:///../../../extensions/cornerstone/src/utils/nthLoader.ts","webpack:///../../../extensions/cornerstone/src/utils/interleave.js","webpack:///../../../extensions/cornerstone/src/utils/getNthFrames.js","webpack:///../../../extensions/cornerstone/src/utils/interleaveTopToBottom.ts","webpack:///../../../extensions/cornerstone/src/utils/findNearbyToolData.ts","webpack:///../../../extensions/cornerstone/src/initContextMenu.ts","webpack:///../../../extensions/cornerstone/src/initDoubleClick.ts","webpack:///../../../extensions/cornerstone/src/utils/initViewTiming.ts","webpack:///../../../extensions/cornerstone/src/init.tsx","webpack:///../../../extensions/cornerstone/src/utils/DicomFileUploader.ts","webpack:///../../../extensions/cornerstone/src/components/DicomUpload/DicomUploadProgressItem.tsx","webpack:///../../../extensions/cornerstone/src/components/DicomUpload/DicomUploadProgress.tsx","webpack:///../../../extensions/cornerstone/src/components/DicomUpload/DicomUpload.tsx","webpack:///../../../extensions/cornerstone/src/getCustomizationModule.ts","webpack:///../../../extensions/cornerstone/src/utils/CornerstoneViewportDownloadForm.tsx","webpack:///../../../extensions/cornerstone/src/utils/stackSync/toggleStackImageSync.ts","webpack:///../../../extensions/cornerstone/src/commandsModule.ts","webpack:///../../../extensions/cornerstone/src/getHangingProtocolModule.ts","webpack:///../../../extensions/cornerstone/src/services/ToolGroupService/ToolGroupService.ts","webpack:///../../../extensions/cornerstone/src/services/ToolGroupService/index.js","webpack:///../../../extensions/cornerstone/src/services/SyncGroupService/SyncGroupService.ts","webpack:///../../../extensions/cornerstone/src/services/SyncGroupService/index.js","webpack:///../../../extensions/cornerstone/src/utils/transitions.ts","webpack:///../../../extensions/cornerstone/src/services/SegmentationService/SegmentationService.ts","webpack:///../../../extensions/cornerstone/src/services/SegmentationService/RTSTRUCT/mapROIContoursToRTStructData.ts","webpack:///../../../extensions/cornerstone/src/services/SegmentationService/index.js","webpack:///../../../extensions/cornerstone/src/utils/getCornerstoneViewportType.ts","webpack:///../../../extensions/cornerstone/src/services/CornerstoneCacheService/CornerstoneCacheService.ts","webpack:///../../../extensions/cornerstone/src/services/CornerstoneCacheService/index.js","webpack:///../../../extensions/cornerstone/src/services/ViewportService/constants.ts","webpack:///../../../extensions/cornerstone/src/services/ViewportService/Viewport.ts","webpack:///../../../extensions/cornerstone/src/utils/getCornerstoneOrientation.ts","webpack:///../../../extensions/cornerstone/src/utils/getCornerstoneBlendMode.ts","webpack:///../../../extensions/cornerstone/src/utils/JumpPresets.ts","webpack:///../../../extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts","webpack:///../../../extensions/cornerstone/src/utils/dicomLoaderService.js","webpack:///../../../extensions/cornerstone/src/id.js","webpack:///../../../extensions/cornerstone/src/index.tsx","webpack:///../../../extensions/cornerstone/src/state.ts","webpack:///../../../extensions/cornerstone/src/utils/measurementServiceMappings/utils/getSOPInstanceAttributes.js"],"sourcesContent":["import * as cornerstone from '@cornerstonejs/core';\nimport { volumeLoader } from '@cornerstonejs/core';\nimport { cornerstoneStreamingImageVolumeLoader } from '@cornerstonejs/streaming-image-volume-loader';\nimport dicomImageLoader, { webWorkerManager } from '@cornerstonejs/dicom-image-loader';\nimport dicomParser from 'dicom-parser';\nimport { errorHandler, utils } from '@ohif/core';\n\nconst { registerVolumeLoader } = volumeLoader;\n\nlet initialized = false;\n\nfunction initWebWorkers(appConfig) {\n const config = {\n maxWebWorkers: Math.min(\n Math.max(navigator.hardwareConcurrency - 1, 1),\n appConfig.maxNumberOfWebWorkers\n ),\n startWebWorkersOnDemand: true,\n taskConfiguration: {\n decodeTask: {\n initializeCodecsOnStartup: false,\n usePDFJS: false,\n strict: false,\n },\n },\n };\n\n if (!initialized) {\n dicomImageLoader.webWorkerManager.initialize(config);\n initialized = true;\n }\n}\n\nexport default function initWADOImageLoader(\n userAuthenticationService,\n appConfig,\n extensionManager\n) {\n dicomImageLoader.external.cornerstone = cornerstone;\n dicomImageLoader.external.dicomParser = dicomParser;\n\n registerVolumeLoader('cornerstoneStreamingImageVolume', cornerstoneStreamingImageVolumeLoader);\n\n dicomImageLoader.configure({\n decodeConfig: {\n // !! IMPORTANT !!\n // We should set this flag to false, since, by default @cornerstonejs/dicom-image-loader\n // will convert everything to integers (to be able to work with cornerstone-2d).\n // Until the default is set to true (which is the case for cornerstone3D),\n // we should set this flag to false.\n convertFloatPixelDataToInt: false,\n use16BitDataType: Boolean(appConfig.use16BitDataType),\n },\n beforeSend: function (xhr) {\n //TODO should be removed in the future and request emitted by DicomWebDataSource\n const sourceConfig = extensionManager.getActiveDataSource()?.[0].getConfig() ?? {};\n const headers = userAuthenticationService.getAuthorizationHeader();\n /*\n const acceptHeader = utils.generateAcceptHeader(\n sourceConfig.acceptHeader,\n sourceConfig.requestTransferSyntaxUID,\n sourceConfig.omitQuotationForMultipartRequest\n );\n */\n const xhrRequestHeaders = {\n Accept: '*/*',\n //Accept: acceptHeader,\n };\n\n if (headers) {\n Object.assign(xhrRequestHeaders, headers);\n }\n\n return xhrRequestHeaders;\n },\n errorInterceptor: error => {\n errorHandler.getHTTPErrorHandler(error);\n },\n });\n\n initWebWorkers(appConfig);\n}\n\nexport function destroy() {\n // Note: we don't want to call .terminate on the webWorkerManager since\n // that resets the config\n const webWorkers = webWorkerManager.webWorkers;\n for (let i = 0; i < webWorkers.length; i++) {\n webWorkers[i].worker.terminate();\n }\n webWorkers.length = 0;\n}\n","import React from 'react';\nimport { Input, Dialog, ButtonEnums } from '@ohif/ui';\n\n/**\n *\n * @param {*} data\n * @param {*} data.text\n * @param {*} data.label\n * @param {*} event\n * @param {*} callback\n * @param {*} isArrowAnnotateInputDialog\n * @param {*} dialogConfig\n * @param {string?} dialogConfig.dialogTitle - title of the input dialog\n * @param {string?} dialogConfig.inputLabel - show label above the input\n */\nfunction callInputDialog(\n uiDialogService,\n data,\n callback,\n isArrowAnnotateInputDialog = true,\n dialogConfig: any = {}\n) {\n const dialogId = 'dialog-enter-annotation';\n const label = data ? (isArrowAnnotateInputDialog ? data.text : data.label) : '';\n const {\n dialogTitle = 'Annotation',\n inputLabel = 'Enter your annotation',\n validateFunc = value => true,\n } = dialogConfig;\n\n const onSubmitHandler = ({ action, value }) => {\n switch (action.id) {\n case 'save':\n if (typeof validateFunc === 'function' && !validateFunc(value.label)) {\n return;\n }\n\n callback(value.label, action.id);\n break;\n case 'cancel':\n callback('', action.id);\n break;\n }\n uiDialogService.dismiss({ id: dialogId });\n };\n\n if (uiDialogService) {\n uiDialogService.create({\n id: dialogId,\n centralize: true,\n isDraggable: false,\n showOverlay: true,\n content: Dialog,\n contentProps: {\n title: dialogTitle,\n value: { label },\n noCloseButton: true,\n onClose: () => uiDialogService.dismiss({ id: dialogId }),\n actions: [\n { id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },\n { id: 'save', text: 'Save', type: ButtonEnums.type.primary },\n ],\n onSubmit: onSubmitHandler,\n body: ({ value, setValue }) => {\n return (\n {\n event.persist();\n setValue(value => ({ ...value, label: event.target.value }));\n }}\n onKeyPress={event => {\n if (event.key === 'Enter') {\n onSubmitHandler({ value, action: { id: 'save' } });\n }\n }}\n />\n );\n },\n },\n });\n }\n}\n\nexport default callInputDialog;\n","import { getEnabledElement } from '@cornerstonejs/core';\nimport { IEnabledElement } from '@cornerstonejs/core/dist/esm/types';\n\nimport { getEnabledElement as OHIFgetEnabledElement } from '../state';\n\nexport default function getActiveViewportEnabledElement(viewportGridService): IEnabledElement {\n const { activeViewportId } = viewportGridService.getState();\n const { element } = OHIFgetEnabledElement(activeViewportId) || {};\n const enabledElement = getEnabledElement(element);\n return enabledElement;\n}\n","import { metaData } from '@cornerstonejs/core';\nimport { LengthTool, utilities } from '@cornerstonejs/tools';\nimport callInputDialog from '../utils/callInputDialog';\nimport getActiveViewportEnabledElement from '../utils/getActiveViewportEnabledElement';\n\nconst { calibrateImageSpacing } = utilities;\n\n/**\n * Calibration Line tool works almost the same as the\n */\nclass CalibrationLineTool extends LengthTool {\n static toolName = 'CalibrationLine';\n\n _renderingViewport: any;\n _lengthToolRenderAnnotation = this.renderAnnotation;\n\n renderAnnotation = (enabledElement, svgDrawingHelper) => {\n const { viewport } = enabledElement;\n this._renderingViewport = viewport;\n return this._lengthToolRenderAnnotation(enabledElement, svgDrawingHelper);\n };\n\n _getTextLines(data, targetId) {\n const [canvasPoint1, canvasPoint2] = data.handles.points.map(p =>\n this._renderingViewport.worldToCanvas(p)\n );\n // for display, round to 2 decimal points\n const lengthPx = Math.round(calculateLength2(canvasPoint1, canvasPoint2) * 100) / 100;\n\n const textLines = [`${lengthPx}px`];\n\n return textLines;\n }\n}\n\nfunction calculateLength2(point1, point2) {\n const dx = point1[0] - point2[0];\n const dy = point1[1] - point2[1];\n return Math.sqrt(dx * dx + dy * dy);\n}\n\nfunction calculateLength3(pos1, pos2) {\n const dx = pos1[0] - pos2[0];\n const dy = pos1[1] - pos2[1];\n const dz = pos1[2] - pos2[2];\n\n return Math.sqrt(dx * dx + dy * dy + dz * dz);\n}\n\nexport default CalibrationLineTool;\n\nexport function onCompletedCalibrationLine(servicesManager, csToolsEvent) {\n const { uiDialogService, viewportGridService } = servicesManager.services;\n\n // calculate length (mm) with the current Pixel Spacing\n const annotationAddedEventDetail = csToolsEvent.detail;\n const {\n annotation: { metadata, data: annotationData },\n } = annotationAddedEventDetail;\n const { referencedImageId: imageId } = metadata;\n const enabledElement = getActiveViewportEnabledElement(viewportGridService);\n const { viewport } = enabledElement;\n\n const length =\n Math.round(\n calculateLength3(annotationData.handles.points[0], annotationData.handles.points[1]) * 100\n ) / 100;\n\n // calculate the currently applied pixel spacing on the viewport\n const calibratedPixelSpacing = metaData.get('calibratedPixelSpacing', imageId);\n const imagePlaneModule = metaData.get('imagePlaneModule', imageId);\n const currentRowPixelSpacing =\n calibratedPixelSpacing?.[0] || imagePlaneModule?.rowPixelSpacing || 1;\n const currentColumnPixelSpacing =\n calibratedPixelSpacing?.[1] || imagePlaneModule?.columnPixelSpacing || 1;\n\n const adjustCalibration = newLength => {\n const spacingScale = newLength / length;\n\n // trigger resize of the viewport to adjust the world/pixel mapping\n calibrateImageSpacing(imageId, viewport.getRenderingEngine(), {\n type: 'User',\n scale: 1 / spacingScale,\n });\n };\n\n return new Promise((resolve, reject) => {\n if (!uiDialogService) {\n reject('UIDialogService is not initiated');\n return;\n }\n\n callInputDialog(\n uiDialogService,\n {\n text: '',\n label: `${length}`,\n },\n (value, id) => {\n if (id === 'save') {\n adjustCalibration(Number.parseFloat(value));\n resolve(true);\n } else {\n reject('cancel');\n }\n },\n false,\n {\n dialogTitle: 'Calibration',\n inputLabel: 'Actual Physical distance (mm)',\n\n // the input value must be a number\n validateFunc: val => {\n try {\n const v = Number.parseFloat(val);\n return !isNaN(v) && v !== 0.0;\n } catch {\n return false;\n }\n },\n }\n );\n });\n}\n","import { VolumeViewport, metaData } from '@cornerstonejs/core';\nimport { utilities } from '@cornerstonejs/core';\nimport { IStackViewport, IVolumeViewport, Point3 } from '@cornerstonejs/core/dist/esm/types';\nimport { AnnotationDisplayTool, drawing } from '@cornerstonejs/tools';\nimport { guid } from '@ohif/core/src/utils';\n\ninterface CachedStat {\n color: number[]; // [r, g, b, a]\n overlays: {\n // ...overlayPlaneModule\n _id: string;\n type: 'G' | 'R'; // G for Graphics, R for ROI\n color?: number[]; // Rendered color [r, g, b, a]\n dataUrl?: string; // Rendered image in Data URL expression\n }[];\n}\n\n/**\n * Image Overlay Viewer tool is not a traditional tool that requires user interactin.\n * But it is used to display Pixel Overlays. And it will provide toggling capability.\n *\n * The documentation for Overlay Plane Module of DICOM can be found in [C.9.2 of\n * Part-3 of DICOM standard](https://dicom.nema.org/medical/dicom/2018b/output/chtml/part03/sect_C.9.2.html)\n *\n * Image Overlay rendered by this tool can be toggled on and off using\n * toolGroup.setToolEnabled() and toolGroup.setToolDisabled()\n */\nclass ImageOverlayViewerTool extends AnnotationDisplayTool {\n static toolName = 'ImageOverlayViewer';\n private _cachedOverlayMetadata: Map = new Map();\n private _cachedStats: { [key: string]: CachedStat } = {};\n\n constructor(\n toolProps = {},\n defaultToolProps = {\n supportedInteractionTypes: [],\n configuration: {\n fillColor: [255, 127, 127, 255],\n },\n }\n ) {\n super(toolProps, defaultToolProps);\n }\n\n onSetToolDisabled = (): void => {\n this._cachedStats = {};\n this._cachedOverlayMetadata = new Map();\n };\n\n protected getReferencedImageId(viewport: IStackViewport | IVolumeViewport): string {\n if (viewport instanceof VolumeViewport) {\n return;\n }\n\n const targetId = this.getTargetId(viewport);\n return targetId.split('imageId:')[1];\n }\n\n renderAnnotation = (enabledElement, svgDrawingHelper) => {\n const { viewport } = enabledElement;\n\n const imageId = this.getReferencedImageId(viewport);\n if (!imageId) {\n return;\n }\n\n const overlays =\n this._cachedOverlayMetadata.get(imageId) ??\n metaData.get('overlayPlaneModule', imageId)?.overlays;\n\n // no overlays\n if (!overlays?.length) {\n return;\n }\n\n this._cachedOverlayMetadata.set(imageId, overlays);\n\n this._getCachedStat(imageId, overlays, this.configuration.fillColor).then(cachedStat => {\n cachedStat.overlays.forEach(overlay => {\n this._renderOverlay(enabledElement, svgDrawingHelper, overlay);\n });\n });\n\n return true;\n };\n\n /**\n * Render to DOM\n *\n * @param enabledElement\n * @param svgDrawingHelper\n * @param overlayData\n * @returns\n */\n private _renderOverlay(enabledElement, svgDrawingHelper, overlayData) {\n const { viewport } = enabledElement;\n const imageId = this.getReferencedImageId(viewport);\n if (!imageId) {\n return;\n }\n\n // Decide the rendering position of the overlay image on the current canvas\n const { _id, columns: width, rows: height, x, y } = overlayData;\n const overlayTopLeftWorldPos = utilities.imageToWorldCoords(imageId, [\n x - 1, // Remind that top-left corner's (x, y) is be (1, 1)\n y - 1,\n ]);\n const overlayTopLeftOnCanvas = viewport.worldToCanvas(overlayTopLeftWorldPos);\n const overlayBottomRightWorldPos = utilities.imageToWorldCoords(imageId, [width, height]);\n const overlayBottomRightOnCanvas = viewport.worldToCanvas(overlayBottomRightWorldPos);\n\n // add image to the annotations svg layer\n const svgns = 'http://www.w3.org/2000/svg';\n const svgNodeHash = `image-overlay-${_id}`;\n const existingImageElement = svgDrawingHelper.getSvgNode(svgNodeHash);\n\n const attributes = {\n 'data-id': svgNodeHash,\n width: overlayBottomRightOnCanvas[0] - overlayTopLeftOnCanvas[0],\n height: overlayBottomRightOnCanvas[1] - overlayTopLeftOnCanvas[1],\n x: overlayTopLeftOnCanvas[0],\n y: overlayTopLeftOnCanvas[1],\n href: overlayData.dataUrl,\n };\n\n if (\n isNaN(attributes.x) ||\n isNaN(attributes.y) ||\n isNaN(attributes.width) ||\n isNaN(attributes.height)\n ) {\n console.warn('Invalid rendering attribute for image overlay', attributes['data-id']);\n return false;\n }\n\n if (existingImageElement) {\n drawing.setAttributesIfNecessary(attributes, existingImageElement);\n svgDrawingHelper.setNodeTouched(svgNodeHash);\n } else {\n const newImageElement = document.createElementNS(svgns, 'image');\n drawing.setNewAttributesIfValid(attributes, newImageElement);\n svgDrawingHelper.appendNode(newImageElement, svgNodeHash);\n }\n return true;\n }\n\n private async _getCachedStat(\n imageId: string,\n overlayMetadata: any[],\n color: number[]\n ): Promise {\n if (this._cachedStats[imageId] && this._isSameColor(this._cachedStats[imageId].color, color)) {\n return this._cachedStats[imageId];\n }\n\n const overlays = await Promise.all(\n overlayMetadata\n .filter(overlay => overlay.pixelData)\n .map(async (overlay, idx) => {\n let pixelData = null;\n if (overlay.pixelData.Value) {\n pixelData = overlay.pixelData.Value;\n } else if (overlay.pixelData instanceof Array) {\n pixelData = overlay.pixelData[0];\n } else if (overlay.pixelData.retrieveBulkData) {\n pixelData = await overlay.pixelData.retrieveBulkData();\n }\n\n if (!pixelData) {\n return;\n }\n\n const dataUrl = this._renderOverlayToDataUrl(\n { width: overlay.columns, height: overlay.rows },\n color,\n pixelData\n );\n\n return {\n ...overlay,\n _id: guid(),\n dataUrl, // this will be a data url expression of the rendered image\n color,\n };\n })\n );\n\n this._cachedStats[imageId] = {\n color: color,\n overlays: overlays.filter(overlay => overlay),\n };\n\n return this._cachedStats[imageId];\n }\n\n /**\n * compare two RGBA expression of colors.\n *\n * @param color1\n * @param color2\n * @returns\n */\n private _isSameColor(color1: number[], color2: number[]) {\n return (\n color1 &&\n color2 &&\n color1[0] === color2[0] &&\n color1[1] === color2[1] &&\n color1[2] === color2[2] &&\n color1[3] === color2[3]\n );\n }\n\n /**\n * pixelData of overlayPlane module is an array of bits corresponding\n * to each of the underlying pixels of the image.\n * Let's create pixel data from bit array of overlay data\n *\n * @param pixelDataRaw\n * @param color\n * @returns\n */\n private _renderOverlayToDataUrl({ width, height }, color, pixelDataRaw) {\n const pixelDataView = new DataView(pixelDataRaw);\n const totalBits = width * height;\n\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n\n const ctx = canvas.getContext('2d');\n ctx.clearRect(0, 0, width, height); // make it transparent\n ctx.globalCompositeOperation = 'copy';\n\n const imageData = ctx.getImageData(0, 0, width, height);\n const data = imageData.data;\n for (let i = 0, bitIdx = 0, byteIdx = 0; i < totalBits; i++) {\n if (pixelDataView.getUint8(byteIdx) & (1 << bitIdx)) {\n data[i * 4] = color[0];\n data[i * 4 + 1] = color[1];\n data[i * 4 + 2] = color[2];\n data[i * 4 + 3] = color[3];\n }\n\n // next bit, byte\n if (bitIdx >= 7) {\n bitIdx = 0;\n byteIdx++;\n } else {\n bitIdx++;\n }\n }\n ctx.putImageData(imageData, 0, 0);\n\n return canvas.toDataURL();\n }\n}\n\nexport default ImageOverlayViewerTool;\n","import {\n PanTool,\n WindowLevelTool,\n StackScrollTool,\n StackScrollMouseWheelTool,\n ZoomTool,\n VolumeRotateMouseWheelTool,\n MIPJumpToClickTool,\n LengthTool,\n RectangleROITool,\n EllipticalROITool,\n CircleROITool,\n BidirectionalTool,\n ArrowAnnotateTool,\n DragProbeTool,\n ProbeTool,\n AngleTool,\n CobbAngleTool,\n PlanarFreehandROITool,\n MagnifyTool,\n CrosshairsTool,\n SegmentationDisplayTool,\n init,\n addTool,\n annotation,\n ReferenceLinesTool,\n TrackballRotateTool,\n CircleScissorsTool,\n RectangleScissorsTool,\n SphereScissorsTool,\n} from '@cornerstonejs/tools';\n\nimport CalibrationLineTool from './tools/CalibrationLineTool';\nimport ImageOverlayViewerTool from './tools/ImageOverlayViewerTool';\n\nexport default function initCornerstoneTools(configuration = {}) {\n CrosshairsTool.isAnnotation = false;\n ReferenceLinesTool.isAnnotation = false;\n\n init(configuration);\n addTool(PanTool);\n addTool(WindowLevelTool);\n addTool(StackScrollMouseWheelTool);\n addTool(StackScrollTool);\n addTool(ZoomTool);\n addTool(ProbeTool);\n addTool(VolumeRotateMouseWheelTool);\n addTool(MIPJumpToClickTool);\n addTool(LengthTool);\n addTool(RectangleROITool);\n addTool(EllipticalROITool);\n addTool(CircleROITool);\n addTool(BidirectionalTool);\n addTool(ArrowAnnotateTool);\n addTool(DragProbeTool);\n addTool(AngleTool);\n addTool(CobbAngleTool);\n addTool(PlanarFreehandROITool);\n addTool(MagnifyTool);\n addTool(CrosshairsTool);\n addTool(SegmentationDisplayTool);\n addTool(ReferenceLinesTool);\n addTool(CalibrationLineTool);\n addTool(TrackballRotateTool);\n addTool(CircleScissorsTool);\n addTool(RectangleScissorsTool);\n addTool(SphereScissorsTool);\n addTool(ImageOverlayViewerTool);\n\n // Modify annotation tools to use dashed lines on SR\n const annotationStyle = {\n textBoxFontSize: '15px',\n lineWidth: '1.5',\n };\n\n const defaultStyles = annotation.config.style.getDefaultToolStyles();\n annotation.config.style.setDefaultToolStyles({\n global: {\n ...defaultStyles.global,\n ...annotationStyle,\n },\n });\n}\n\nconst toolNames = {\n Pan: PanTool.toolName,\n ArrowAnnotate: ArrowAnnotateTool.toolName,\n WindowLevel: WindowLevelTool.toolName,\n StackScroll: StackScrollTool.toolName,\n StackScrollMouseWheel: StackScrollMouseWheelTool.toolName,\n Zoom: ZoomTool.toolName,\n VolumeRotateMouseWheel: VolumeRotateMouseWheelTool.toolName,\n MipJumpToClick: MIPJumpToClickTool.toolName,\n Length: LengthTool.toolName,\n DragProbe: DragProbeTool.toolName,\n Probe: ProbeTool.toolName,\n RectangleROI: RectangleROITool.toolName,\n EllipticalROI: EllipticalROITool.toolName,\n CircleROI: CircleROITool.toolName,\n Bidirectional: BidirectionalTool.toolName,\n Angle: AngleTool.toolName,\n CobbAngle: CobbAngleTool.toolName,\n PlanarFreehandROI: PlanarFreehandROITool.toolName,\n Magnify: MagnifyTool.toolName,\n Crosshairs: CrosshairsTool.toolName,\n SegmentationDisplay: SegmentationDisplayTool.toolName,\n ReferenceLines: ReferenceLinesTool.toolName,\n CalibrationLine: CalibrationLineTool.toolName,\n TrackballRotateTool: TrackballRotateTool.toolName,\n CircleScissors: CircleScissorsTool.toolName,\n RectangleScissors: RectangleScissorsTool.toolName,\n SphereScissors: SphereScissorsTool.toolName,\n ImageOverlayViewer: ImageOverlayViewerTool.toolName,\n};\n\nexport { toolNames };\n","export default [\n 'Length',\n 'EllipticalROI',\n 'CircleROI',\n 'Bidirectional',\n 'ArrowAnnotate',\n 'Angle',\n 'CobbAngle',\n 'Probe',\n 'RectangleROI',\n 'PlanarFreehandROI',\n];\n","import SUPPORTED_TOOLS from './constants/supportedTools';\nimport getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';\nimport { utils } from '@ohif/core';\n\nconst Length = {\n toAnnotation: measurement => {},\n\n /**\n * Maps cornerstone annotation event data to measurement service format.\n *\n * @param {Object} cornerstone Cornerstone event data\n * @return {Measurement} Measurement instance\n */\n toMeasurement: (\n csToolsEventDetail,\n displaySetService,\n cornerstoneViewportService,\n getValueTypeFromToolType\n ) => {\n const { annotation, viewportId } = csToolsEventDetail;\n const { metadata, data, annotationUID } = annotation;\n\n if (!metadata || !data) {\n console.warn('Length tool: Missing metadata or data');\n return null;\n }\n\n const { toolName, referencedImageId, FrameOfReferenceUID } = metadata;\n const validToolType = SUPPORTED_TOOLS.includes(toolName);\n\n if (!validToolType) {\n throw new Error('Tool not supported');\n }\n\n const {\n SOPInstanceUID,\n SeriesInstanceUID,\n StudyInstanceUID,\n } = getSOPInstanceAttributes(\n referencedImageId,\n cornerstoneViewportService,\n viewportId\n );\n\n let displaySet;\n\n if (SOPInstanceUID) {\n displaySet = displaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID\n );\n } else {\n displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);\n }\n\n const { points } = data.handles;\n\n const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);\n\n const displayText = getDisplayText(mappedAnnotations, displaySet);\n const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);\n\n return {\n uid: annotationUID,\n SOPInstanceUID,\n FrameOfReferenceUID,\n points,\n metadata,\n referenceSeriesUID: SeriesInstanceUID,\n referenceStudyUID: StudyInstanceUID,\n frameNumber: mappedAnnotations[0]?.frameNumber || 1,\n toolName: metadata.toolName,\n displaySetInstanceUID: displaySet.displaySetInstanceUID,\n label: data.label,\n displayText: displayText,\n data: data.cachedStats,\n type: getValueTypeFromToolType(toolName),\n getReport,\n };\n },\n};\n\nfunction getMappedAnnotations(annotation, displaySetService) {\n const { metadata, data } = annotation;\n const { cachedStats } = data;\n const { referencedImageId } = metadata;\n const targets = Object.keys(cachedStats);\n\n if (!targets.length) {\n return [];\n }\n\n const annotations = [];\n Object.keys(cachedStats).forEach(targetId => {\n const targetStats = cachedStats[targetId];\n\n if (!referencedImageId) {\n throw new Error('Non-acquisition plane measurement mapping not supported');\n }\n\n const {\n SOPInstanceUID,\n SeriesInstanceUID,\n frameNumber,\n } = getSOPInstanceAttributes(referencedImageId);\n\n const displaySet = displaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID,\n frameNumber\n );\n\n const { SeriesNumber } = displaySet;\n const { length, unit = 'mm' } = targetStats;\n\n annotations.push({\n SeriesInstanceUID,\n SOPInstanceUID,\n SeriesNumber,\n frameNumber,\n unit,\n length,\n });\n });\n\n return annotations;\n}\n\n/*\nThis function is used to convert the measurement data to a format that is\nsuitable for the report generation (e.g. for the csv report). The report\nreturns a list of columns and corresponding values.\n*/\nfunction _getReport(mappedAnnotations, points, FrameOfReferenceUID) {\n const columns = [];\n const values = [];\n\n // Add Type\n columns.push('AnnotationType');\n values.push('Cornerstone:Length');\n\n mappedAnnotations.forEach(annotation => {\n const { length, unit } = annotation;\n columns.push(`Length`);\n values.push(length);\n columns.push('Unit');\n values.push(unit);\n });\n\n if (FrameOfReferenceUID) {\n columns.push('FrameOfReferenceUID');\n values.push(FrameOfReferenceUID);\n }\n\n if (points) {\n columns.push('points');\n // points has the form of [[x1, y1, z1], [x2, y2, z2], ...]\n // convert it to string of [[x1 y1 z1];[x2 y2 z2];...]\n // so that it can be used in the csv report\n values.push(points.map(p => p.join(' ')).join(';'));\n }\n\n return {\n columns,\n values,\n };\n}\n\nfunction getDisplayText(mappedAnnotations, displaySet) {\n if (!mappedAnnotations || !mappedAnnotations.length) {\n return '';\n }\n\n const displayText = [];\n\n // Area is the same for all series\n const {\n length,\n SeriesNumber,\n SOPInstanceUID,\n frameNumber,\n unit,\n } = mappedAnnotations[0];\n\n const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);\n\n let InstanceNumber;\n if (instance) {\n InstanceNumber = instance.InstanceNumber;\n }\n\n const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';\n const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';\n\n if (length === null || length === undefined) {\n return displayText;\n }\n const roundedLength = utils.roundNumber(length, 2);\n displayText.push(\n `${roundedLength} ${unit} (S: ${SeriesNumber}${instanceText}${frameText})`\n );\n\n return displayText;\n}\n\nexport default Length;\n","export default function getHandlesFromPoints(points) {\n if (points.longAxis && points.shortAxis) {\n const handles = {};\n handles.start = points.longAxis[0];\n handles.end = points.longAxis[1];\n handles.perpendicularStart = points.longAxis[0];\n handles.perpendicularEnd = points.longAxis[1];\n return handles;\n }\n\n return points\n .map((p, i) => (i % 10 === 0 ? { start: p } : { end: p }))\n .reduce((obj, item) => Object.assign(obj, { ...item }), {});\n}\n","import { annotation as cs3dToolAnnotationUtils } from '@cornerstonejs/tools';\n\n/**\n * Check whether an annotation from imaging library is selected or not.\n * @param {string} annotationUID uid of imaging library annotation\n * @returns boolean\n */\nfunction isAnnotationSelected(annotationUID: string): boolean {\n return cs3dToolAnnotationUtils.selection.isAnnotationSelected(annotationUID);\n}\n\n/**\n * Change an annotation from imaging library's selected property.\n * @param annotationUID - uid of imaging library annotation\n * @param selected - new value for selected\n */\nfunction setAnnotationSelected(annotationUID: string, selected: boolean): void {\n const isCurrentSelected = isAnnotationSelected(annotationUID);\n // branch cut, avoid invoking imaging library unnecessarily.\n if (isCurrentSelected !== selected) {\n cs3dToolAnnotationUtils.selection.setAnnotationSelected(annotationUID, selected);\n }\n}\n\nfunction getFirstAnnotationSelected(element) {\n const [selectedAnnotationUID] = cs3dToolAnnotationUtils.selection.getAnnotationsSelected() || [];\n\n if (selectedAnnotationUID) {\n return cs3dToolAnnotationUtils.state.getAnnotation(selectedAnnotationUID);\n }\n}\n\nexport { isAnnotationSelected, setAnnotationSelected, getFirstAnnotationSelected };\n","const getDisplayUnit = unit => (unit == null ? '' : unit);\n\nexport default getDisplayUnit;\n","import { annotation } from '@cornerstonejs/tools';\n\nimport SUPPORTED_TOOLS from './constants/supportedTools';\nimport getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';\nimport { utils } from '@ohif/core';\nimport { getDisplayUnit } from './utils';\n\nconst Bidirectional = {\n toAnnotation: measurement => {},\n toMeasurement: (\n csToolsEventDetail,\n displaySetService,\n cornerstoneViewportService,\n getValueTypeFromToolType\n ) => {\n const { annotation, viewportId } = csToolsEventDetail;\n const { metadata, data, annotationUID } = annotation;\n\n if (!metadata || !data) {\n console.warn('Length tool: Missing metadata or data');\n return null;\n }\n\n const { toolName, referencedImageId, FrameOfReferenceUID } = metadata;\n const validToolType = SUPPORTED_TOOLS.includes(toolName);\n\n if (!validToolType) {\n throw new Error('Tool not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(\n referencedImageId,\n cornerstoneViewportService,\n viewportId\n );\n\n let displaySet;\n\n if (SOPInstanceUID) {\n displaySet = displaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID\n );\n } else {\n displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);\n }\n\n const { points } = data.handles;\n\n const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);\n\n const displayText = getDisplayText(mappedAnnotations, displaySet);\n const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);\n\n return {\n uid: annotationUID,\n SOPInstanceUID,\n FrameOfReferenceUID,\n points,\n metadata,\n referenceSeriesUID: SeriesInstanceUID,\n referenceStudyUID: StudyInstanceUID,\n frameNumber: mappedAnnotations[0]?.frameNumber || 1,\n toolName: metadata.toolName,\n displaySetInstanceUID: displaySet.displaySetInstanceUID,\n label: data.label,\n displayText: displayText,\n data: data.cachedStats,\n type: getValueTypeFromToolType(toolName),\n getReport,\n };\n },\n};\n\nfunction getMappedAnnotations(annotation, displaySetService) {\n const { metadata, data } = annotation;\n const { cachedStats } = data;\n const { referencedImageId, referencedSeriesInstanceUID } = metadata;\n const targets = Object.keys(cachedStats);\n\n if (!targets.length) {\n return [];\n }\n\n const annotations = [];\n Object.keys(cachedStats).forEach(targetId => {\n const targetStats = cachedStats[targetId];\n\n if (!referencedImageId) {\n throw new Error('Non-acquisition plane measurement mapping not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =\n getSOPInstanceAttributes(referencedImageId);\n\n const displaySet = displaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID,\n frameNumber\n );\n\n const { SeriesNumber } = displaySet;\n const { length, width, unit } = targetStats;\n\n annotations.push({\n SeriesInstanceUID,\n SOPInstanceUID,\n SeriesNumber,\n frameNumber,\n unit,\n length,\n width,\n });\n });\n\n return annotations;\n}\n\n/*\nThis function is used to convert the measurement data to a format that is\nsuitable for the report generation (e.g. for the csv report). The report\nreturns a list of columns and corresponding values.\n*/\nfunction _getReport(mappedAnnotations, points, FrameOfReferenceUID) {\n const columns = [];\n const values = [];\n\n // Add Type\n columns.push('AnnotationType');\n values.push('Cornerstone:Bidirectional');\n\n mappedAnnotations.forEach(annotation => {\n const { length, width, unit } = annotation;\n columns.push(`Length`, `Width`, 'Unit');\n values.push(length, width, unit);\n });\n\n if (FrameOfReferenceUID) {\n columns.push('FrameOfReferenceUID');\n values.push(FrameOfReferenceUID);\n }\n\n if (points) {\n columns.push('points');\n // points has the form of [[x1, y1, z1], [x2, y2, z2], ...]\n // convert it to string of [[x1 y1 z1];[x2 y2 z2];...]\n // so that it can be used in the csv report\n values.push(points.map(p => p.join(' ')).join(';'));\n }\n\n return {\n columns,\n values,\n };\n}\n\nfunction getDisplayText(mappedAnnotations, displaySet) {\n if (!mappedAnnotations || !mappedAnnotations.length) {\n return '';\n }\n\n const displayText = [];\n\n // Area is the same for all series\n const { length, width, unit, SeriesNumber, SOPInstanceUID, frameNumber } = mappedAnnotations[0];\n const roundedLength = utils.roundNumber(length, 2);\n const roundedWidth = utils.roundNumber(width, 2);\n\n const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);\n\n let InstanceNumber;\n if (instance) {\n InstanceNumber = instance.InstanceNumber;\n }\n\n const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';\n const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';\n\n displayText.push(\n `L: ${roundedLength} ${getDisplayUnit(unit)} (S: ${SeriesNumber}${instanceText}${frameText})`\n );\n displayText.push(`W: ${roundedWidth} ${getDisplayUnit(unit)}`);\n\n return displayText;\n}\n\nexport default Bidirectional;\n","import SUPPORTED_TOOLS from './constants/supportedTools';\nimport { getDisplayUnit } from './utils';\nimport getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';\nimport { utils } from '@ohif/core';\n\nconst EllipticalROI = {\n toAnnotation: measurement => {},\n toMeasurement: (\n csToolsEventDetail,\n displaySetService,\n cornerstoneViewportService,\n getValueTypeFromToolType\n ) => {\n const { annotation, viewportId } = csToolsEventDetail;\n const { metadata, data, annotationUID } = annotation;\n\n if (!metadata || !data) {\n console.warn('Length tool: Missing metadata or data');\n return null;\n }\n\n const { toolName, referencedImageId, FrameOfReferenceUID } = metadata;\n const validToolType = SUPPORTED_TOOLS.includes(toolName);\n\n if (!validToolType) {\n throw new Error('Tool not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(\n referencedImageId,\n cornerstoneViewportService,\n viewportId\n );\n\n let displaySet;\n\n if (SOPInstanceUID) {\n displaySet = displaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID\n );\n } else {\n displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);\n }\n\n const { points } = data.handles;\n\n const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);\n\n const displayText = getDisplayText(mappedAnnotations, displaySet);\n const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);\n\n return {\n uid: annotationUID,\n SOPInstanceUID,\n FrameOfReferenceUID,\n points,\n metadata,\n referenceSeriesUID: SeriesInstanceUID,\n referenceStudyUID: StudyInstanceUID,\n frameNumber: mappedAnnotations[0]?.frameNumber || 1,\n toolName: metadata.toolName,\n displaySetInstanceUID: displaySet.displaySetInstanceUID,\n label: data.label,\n displayText: displayText,\n data: data.cachedStats,\n type: getValueTypeFromToolType(toolName),\n getReport,\n };\n },\n};\n\nfunction getMappedAnnotations(annotation, displaySetService) {\n const { metadata, data } = annotation;\n const { cachedStats } = data;\n const { referencedImageId } = metadata;\n const targets = Object.keys(cachedStats);\n\n if (!targets.length) {\n return [];\n }\n\n const annotations = [];\n Object.keys(cachedStats).forEach(targetId => {\n const targetStats = cachedStats[targetId];\n\n if (!referencedImageId) {\n // Todo: Non-acquisition plane measurement mapping not supported yet\n throw new Error('Non-acquisition plane measurement mapping not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =\n getSOPInstanceAttributes(referencedImageId);\n\n const displaySet = displaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID,\n frameNumber\n );\n\n const { SeriesNumber } = displaySet;\n const { mean, stdDev, max, area, Modality, areaUnit, modalityUnit } = targetStats;\n\n annotations.push({\n SeriesInstanceUID,\n SOPInstanceUID,\n SeriesNumber,\n frameNumber,\n Modality,\n unit: modalityUnit,\n areaUnit,\n mean,\n stdDev,\n max,\n area,\n });\n });\n\n return annotations;\n}\n\n/*\nThis function is used to convert the measurement data to a format that is\nsuitable for the report generation (e.g. for the csv report). The report\nreturns a list of columns and corresponding values.\n*/\nfunction _getReport(mappedAnnotations, points, FrameOfReferenceUID) {\n const columns = [];\n const values = [];\n\n // Add Type\n columns.push('AnnotationType');\n values.push('Cornerstone:EllipticalROI');\n\n mappedAnnotations.forEach(annotation => {\n const { mean, stdDev, max, area, unit, areaUnit } = annotation;\n\n if (!mean || !unit || !max || !area) {\n return;\n }\n\n columns.push(`max (${unit})`, `mean (${unit})`, `std (${unit})`, 'Area', 'Unit');\n values.push(max, mean, stdDev, area, areaUnit);\n });\n\n if (FrameOfReferenceUID) {\n columns.push('FrameOfReferenceUID');\n values.push(FrameOfReferenceUID);\n }\n\n if (points) {\n columns.push('points');\n // points has the form of [[x1, y1, z1], [x2, y2, z2], ...]\n // convert it to string of [[x1 y1 z1];[x2 y2 z2];...]\n // so that it can be used in the csv report\n values.push(points.map(p => p.join(' ')).join(';'));\n }\n\n return {\n columns,\n values,\n };\n}\n\nfunction getDisplayText(mappedAnnotations, displaySet) {\n if (!mappedAnnotations || !mappedAnnotations.length) {\n return '';\n }\n\n const displayText = [];\n\n // Area is the same for all series\n const { area, SOPInstanceUID, frameNumber, areaUnit } = mappedAnnotations[0];\n\n const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);\n\n let InstanceNumber;\n if (instance) {\n InstanceNumber = instance.InstanceNumber;\n }\n\n const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';\n const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';\n\n const roundedArea = utils.roundNumber(area, 2);\n displayText.push(`${roundedArea} ${getDisplayUnit(areaUnit)}`);\n\n // Todo: we need a better UI for displaying all these information\n mappedAnnotations.forEach(mappedAnnotation => {\n const { unit, max, SeriesNumber } = mappedAnnotation;\n\n let maxStr = '';\n if (max) {\n const roundedMax = utils.roundNumber(max, 2);\n maxStr = `Max: ${roundedMax} ${getDisplayUnit(unit)} `;\n }\n\n const str = `${maxStr}(S:${SeriesNumber}${instanceText}${frameText})`;\n if (!displayText.includes(str)) {\n displayText.push(str);\n }\n });\n\n return displayText;\n}\n\nexport default EllipticalROI;\n","import SUPPORTED_TOOLS from './constants/supportedTools';\nimport { getDisplayUnit } from './utils';\nimport getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';\nimport { utils } from '@ohif/core';\n\nconst CircleROI = {\n toAnnotation: measurement => {},\n toMeasurement: (\n csToolsEventDetail,\n DisplaySetService,\n CornerstoneViewportService,\n getValueTypeFromToolType\n ) => {\n const { annotation, viewportId } = csToolsEventDetail;\n const { metadata, data, annotationUID } = annotation;\n\n if (!metadata || !data) {\n console.warn('Length tool: Missing metadata or data');\n return null;\n }\n\n const { toolName, referencedImageId, FrameOfReferenceUID } = metadata;\n const validToolType = SUPPORTED_TOOLS.includes(toolName);\n\n if (!validToolType) {\n throw new Error('Tool not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(\n referencedImageId,\n CornerstoneViewportService,\n viewportId\n );\n\n let displaySet;\n\n if (SOPInstanceUID) {\n displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID\n );\n } else {\n displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID);\n }\n\n const { points } = data.handles;\n\n const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);\n\n const displayText = getDisplayText(mappedAnnotations, displaySet);\n const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);\n\n return {\n uid: annotationUID,\n SOPInstanceUID,\n FrameOfReferenceUID,\n points,\n metadata,\n referenceSeriesUID: SeriesInstanceUID,\n referenceStudyUID: StudyInstanceUID,\n frameNumber: mappedAnnotations[0]?.frameNumber || 1,\n toolName: metadata.toolName,\n displaySetInstanceUID: displaySet.displaySetInstanceUID,\n label: data.label,\n displayText: displayText,\n data: data.cachedStats,\n type: getValueTypeFromToolType(toolName),\n getReport,\n };\n },\n};\n\nfunction getMappedAnnotations(annotation, DisplaySetService) {\n const { metadata, data } = annotation;\n const { cachedStats } = data;\n const { referencedImageId } = metadata;\n const targets = Object.keys(cachedStats);\n\n if (!targets.length) {\n return [];\n }\n\n const annotations = [];\n Object.keys(cachedStats).forEach(targetId => {\n const targetStats = cachedStats[targetId];\n\n if (!referencedImageId) {\n // Todo: Non-acquisition plane measurement mapping not supported yet\n throw new Error('Non-acquisition plane measurement mapping not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =\n getSOPInstanceAttributes(referencedImageId);\n\n const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID,\n frameNumber\n );\n\n const { SeriesNumber } = displaySet;\n const { mean, stdDev, max, area, Modality, areaUnit, modalityUnit } = targetStats;\n\n annotations.push({\n SeriesInstanceUID,\n SOPInstanceUID,\n SeriesNumber,\n frameNumber,\n Modality,\n unit: modalityUnit,\n mean,\n stdDev,\n max,\n area,\n areaUnit,\n });\n });\n\n return annotations;\n}\n\n/*\nThis function is used to convert the measurement data to a format that is\nsuitable for the report generation (e.g. for the csv report). The report\nreturns a list of columns and corresponding values.\n*/\nfunction _getReport(mappedAnnotations, points, FrameOfReferenceUID) {\n const columns = [];\n const values = [];\n\n // Add Type\n columns.push('AnnotationType');\n values.push('Cornerstone:CircleROI');\n\n mappedAnnotations.forEach(annotation => {\n const { mean, stdDev, max, area, unit, areaUnit } = annotation;\n\n if (!mean || !unit || !max || !area) {\n return;\n }\n\n columns.push(`max (${unit})`, `mean (${unit})`, `std (${unit})`, 'Area', 'Unit');\n values.push(max, mean, stdDev, area, areaUnit);\n });\n\n if (FrameOfReferenceUID) {\n columns.push('FrameOfReferenceUID');\n values.push(FrameOfReferenceUID);\n }\n\n if (points) {\n columns.push('points');\n // points has the form of [[x1, y1, z1], [x2, y2, z2], ...]\n // convert it to string of [[x1 y1 z1];[x2 y2 z2];...]\n // so that it can be used in the csv report\n values.push(points.map(p => p.join(' ')).join(';'));\n }\n\n return {\n columns,\n values,\n };\n}\n\nfunction getDisplayText(mappedAnnotations, displaySet) {\n if (!mappedAnnotations || !mappedAnnotations.length) {\n return '';\n }\n\n const displayText = [];\n\n // Area is the same for all series\n const { area, SOPInstanceUID, frameNumber, areaUnit } = mappedAnnotations[0];\n\n const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);\n\n let InstanceNumber;\n if (instance) {\n InstanceNumber = instance.InstanceNumber;\n }\n\n const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';\n const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';\n\n // Area sometimes becomes undefined if `preventHandleOutsideImage` is off.\n const roundedArea = utils.roundNumber(area || 0, 2);\n displayText.push(`${roundedArea} ${getDisplayUnit(areaUnit)}`);\n\n // Todo: we need a better UI for displaying all these information\n mappedAnnotations.forEach(mappedAnnotation => {\n const { unit, max, SeriesNumber } = mappedAnnotation;\n\n let maxStr = '';\n if (max) {\n const roundedMax = utils.roundNumber(max, 2);\n maxStr = `Max: ${roundedMax} ${getDisplayUnit(unit)} `;\n }\n\n const str = `${maxStr}(S:${SeriesNumber}${instanceText}${frameText})`;\n if (!displayText.includes(str)) {\n displayText.push(str);\n }\n });\n\n return displayText;\n}\n\nexport default CircleROI;\n","import SUPPORTED_TOOLS from './constants/supportedTools';\nimport getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';\n\nconst Length = {\n toAnnotation: measurement => {},\n\n /**\n * Maps cornerstone annotation event data to measurement service format.\n *\n * @param {Object} cornerstone Cornerstone event data\n * @return {Measurement} Measurement instance\n */\n toMeasurement: (\n csToolsEventDetail,\n displaySetService,\n cornerstoneViewportService,\n getValueTypeFromToolType\n ) => {\n const { annotation, viewportId } = csToolsEventDetail;\n const { metadata, data, annotationUID } = annotation;\n\n if (!metadata || !data) {\n console.warn('Length tool: Missing metadata or data');\n return null;\n }\n\n const { toolName, referencedImageId, FrameOfReferenceUID } = metadata;\n const validToolType = SUPPORTED_TOOLS.includes(toolName);\n\n if (!validToolType) {\n throw new Error('Tool not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(\n referencedImageId,\n cornerstoneViewportService,\n viewportId\n );\n\n let displaySet;\n\n if (SOPInstanceUID) {\n displaySet = displaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID\n );\n } else {\n displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);\n }\n\n const { points } = data.handles;\n\n const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);\n\n const displayText = getDisplayText(mappedAnnotations, displaySet);\n\n return {\n uid: annotationUID,\n SOPInstanceUID,\n FrameOfReferenceUID,\n points,\n metadata,\n referenceSeriesUID: SeriesInstanceUID,\n referenceStudyUID: StudyInstanceUID,\n frameNumber: mappedAnnotations[0]?.frameNumber || 1,\n toolName: metadata.toolName,\n displaySetInstanceUID: displaySet.displaySetInstanceUID,\n label: data.text,\n text: data.text,\n displayText: displayText,\n data: data.cachedStats,\n type: getValueTypeFromToolType(toolName),\n getReport: () => {\n throw new Error('Not implemented');\n },\n };\n },\n};\n\nfunction getMappedAnnotations(annotation, displaySetService) {\n const { metadata, data } = annotation;\n const { text } = data;\n const { referencedImageId } = metadata;\n\n const annotations = [];\n\n const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =\n getSOPInstanceAttributes(referencedImageId);\n\n const displaySet = displaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID,\n frameNumber\n );\n\n const { SeriesNumber } = displaySet;\n\n annotations.push({\n SeriesInstanceUID,\n SOPInstanceUID,\n SeriesNumber,\n frameNumber,\n text,\n });\n\n return annotations;\n}\n\nfunction getDisplayText(mappedAnnotations, displaySet) {\n if (!mappedAnnotations) {\n return '';\n }\n\n const displayText = [];\n\n // Area is the same for all series\n const { SeriesNumber, SOPInstanceUID, frameNumber } = mappedAnnotations[0];\n\n const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);\n\n let InstanceNumber;\n if (instance) {\n InstanceNumber = instance.InstanceNumber;\n }\n\n const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';\n const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';\n\n displayText.push(`(S: ${SeriesNumber}${instanceText}${frameText})`);\n\n return displayText;\n}\n\nexport default Length;\n","import SUPPORTED_TOOLS from './constants/supportedTools';\nimport { getDisplayUnit } from './utils';\nimport getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';\nimport { utils } from '@ohif/core';\n\nconst CobbAngle = {\n toAnnotation: measurement => {},\n\n /**\n * Maps cornerstone annotation event data to measurement service format.\n *\n * @param {Object} cornerstone Cornerstone event data\n * @return {Measurement} Measurement instance\n */\n toMeasurement: (\n csToolsEventDetail,\n displaySetService,\n CornerstoneViewportService,\n getValueTypeFromToolType\n ) => {\n const { annotation, viewportId } = csToolsEventDetail;\n const { metadata, data, annotationUID } = annotation;\n\n if (!metadata || !data) {\n console.warn('Cobb Angle tool: Missing metadata or data');\n return null;\n }\n\n const { toolName, referencedImageId, FrameOfReferenceUID } = metadata;\n const validToolType = SUPPORTED_TOOLS.includes(toolName);\n\n if (!validToolType) {\n throw new Error('Tool not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(\n referencedImageId,\n CornerstoneViewportService,\n viewportId\n );\n\n let displaySet;\n\n if (SOPInstanceUID) {\n displaySet = displaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID\n );\n } else {\n displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);\n }\n\n const { points } = data.handles;\n\n const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);\n\n const displayText = getDisplayText(mappedAnnotations, displaySet);\n const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);\n\n return {\n uid: annotationUID,\n SOPInstanceUID,\n FrameOfReferenceUID,\n points,\n metadata,\n referenceSeriesUID: SeriesInstanceUID,\n referenceStudyUID: StudyInstanceUID,\n frameNumber: mappedAnnotations?.[0]?.frameNumber || 1,\n toolName: metadata.toolName,\n displaySetInstanceUID: displaySet.displaySetInstanceUID,\n label: data.label,\n displayText: displayText,\n data: data.cachedStats,\n type: getValueTypeFromToolType(toolName),\n getReport,\n };\n },\n};\n\nfunction getMappedAnnotations(annotation, DisplaySetService) {\n const { metadata, data } = annotation;\n const { cachedStats } = data;\n const { referencedImageId } = metadata;\n const targets = Object.keys(cachedStats);\n\n if (!targets.length) {\n return;\n }\n\n const annotations = [];\n Object.keys(cachedStats).forEach(targetId => {\n const targetStats = cachedStats[targetId];\n\n if (!referencedImageId) {\n throw new Error('Non-acquisition plane measurement mapping not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =\n getSOPInstanceAttributes(referencedImageId);\n\n const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID,\n frameNumber\n );\n\n const { SeriesNumber } = displaySet;\n const { angle } = targetStats;\n const unit = '\\u00B0';\n\n annotations.push({\n SeriesInstanceUID,\n SOPInstanceUID,\n SeriesNumber,\n frameNumber,\n unit,\n angle,\n });\n });\n\n return annotations;\n}\n\n/*\nThis function is used to convert the measurement data to a format that is\nsuitable for the report generation (e.g. for the csv report). The report\nreturns a list of columns and corresponding values.\n*/\nfunction _getReport(mappedAnnotations, points, FrameOfReferenceUID) {\n const columns = [];\n const values = [];\n\n // Add Type\n columns.push('AnnotationType');\n values.push('Cornerstone:CobbAngle');\n\n mappedAnnotations.forEach(annotation => {\n const { angle, unit } = annotation;\n columns.push(`Angle (${unit})`);\n values.push(angle);\n });\n\n if (FrameOfReferenceUID) {\n columns.push('FrameOfReferenceUID');\n values.push(FrameOfReferenceUID);\n }\n\n if (points) {\n columns.push('points');\n // points has the form of [[x1, y1, z1], [x2, y2, z2], ...]\n // convert it to string of [[x1 y1 z1];[x2 y2 z2];...]\n // so that it can be used in the csv report\n values.push(points.map(p => p.join(' ')).join(';'));\n }\n\n return {\n columns,\n values,\n };\n}\n\nfunction getDisplayText(mappedAnnotations, displaySet) {\n if (!mappedAnnotations || !mappedAnnotations.length) {\n return '';\n }\n\n const displayText = [];\n\n // Area is the same for all series\n const { angle, unit, SeriesNumber, SOPInstanceUID, frameNumber } = mappedAnnotations[0];\n\n const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);\n\n let InstanceNumber;\n if (instance) {\n InstanceNumber = instance.InstanceNumber;\n }\n\n const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';\n const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';\n if (angle === undefined) {\n return displayText;\n }\n const roundedAngle = utils.roundNumber(angle, 2);\n displayText.push(\n `${roundedAngle} ${getDisplayUnit(unit)} (S: ${SeriesNumber}${instanceText}${frameText})`\n );\n\n return displayText;\n}\n\nexport default CobbAngle;\n","import SUPPORTED_TOOLS from './constants/supportedTools';\nimport { getDisplayUnit } from './utils';\nimport getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';\nimport { utils } from '@ohif/core';\n\nconst Angle = {\n toAnnotation: measurement => {},\n\n /**\n * Maps cornerstone annotation event data to measurement service format.\n *\n * @param {Object} cornerstone Cornerstone event data\n * @return {Measurement} Measurement instance\n */\n toMeasurement: (\n csToolsEventDetail,\n displaySetService,\n CornerstoneViewportService,\n getValueTypeFromToolType\n ) => {\n const { annotation, viewportId } = csToolsEventDetail;\n const { metadata, data, annotationUID } = annotation;\n\n if (!metadata || !data) {\n console.warn('Length tool: Missing metadata or data');\n return null;\n }\n\n const { toolName, referencedImageId, FrameOfReferenceUID } = metadata;\n const validToolType = SUPPORTED_TOOLS.includes(toolName);\n\n if (!validToolType) {\n throw new Error('Tool not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(\n referencedImageId,\n CornerstoneViewportService,\n viewportId\n );\n\n let displaySet;\n\n if (SOPInstanceUID) {\n displaySet = displaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID\n );\n } else {\n displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);\n }\n\n const { points } = data.handles;\n\n const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);\n\n const displayText = getDisplayText(mappedAnnotations, displaySet);\n const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);\n\n return {\n uid: annotationUID,\n SOPInstanceUID,\n FrameOfReferenceUID,\n points,\n metadata,\n referenceSeriesUID: SeriesInstanceUID,\n referenceStudyUID: StudyInstanceUID,\n frameNumber: mappedAnnotations?.[0]?.frameNumber || 1,\n toolName: metadata.toolName,\n displaySetInstanceUID: displaySet.displaySetInstanceUID,\n label: data.label,\n displayText: displayText,\n data: data.cachedStats,\n type: getValueTypeFromToolType(toolName),\n getReport,\n };\n },\n};\n\nfunction getMappedAnnotations(annotation, DisplaySetService) {\n const { metadata, data } = annotation;\n const { cachedStats } = data;\n const { referencedImageId } = metadata;\n const targets = Object.keys(cachedStats);\n\n if (!targets.length) {\n return;\n }\n\n const annotations = [];\n Object.keys(cachedStats).forEach(targetId => {\n const targetStats = cachedStats[targetId];\n\n if (!referencedImageId) {\n throw new Error('Non-acquisition plane measurement mapping not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =\n getSOPInstanceAttributes(referencedImageId);\n\n const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID,\n frameNumber\n );\n\n const { SeriesNumber } = displaySet;\n const { angle } = targetStats;\n const unit = '\\u00B0';\n\n annotations.push({\n SeriesInstanceUID,\n SOPInstanceUID,\n SeriesNumber,\n frameNumber,\n unit,\n angle,\n });\n });\n\n return annotations;\n}\n\n/*\nThis function is used to convert the measurement data to a format that is\nsuitable for the report generation (e.g. for the csv report). The report\nreturns a list of columns and corresponding values.\n*/\nfunction _getReport(mappedAnnotations, points, FrameOfReferenceUID) {\n const columns = [];\n const values = [];\n\n // Add Type\n columns.push('AnnotationType');\n values.push('Cornerstone:Angle');\n\n mappedAnnotations.forEach(annotation => {\n const { angle, unit } = annotation;\n columns.push(`Angle (${unit})`);\n values.push(angle);\n });\n\n if (FrameOfReferenceUID) {\n columns.push('FrameOfReferenceUID');\n values.push(FrameOfReferenceUID);\n }\n\n if (points) {\n columns.push('points');\n // points has the form of [[x1, y1, z1], [x2, y2, z2], ...]\n // convert it to string of [[x1 y1 z1];[x2 y2 z2];...]\n // so that it can be used in the csv report\n values.push(points.map(p => p.join(' ')).join(';'));\n }\n\n return {\n columns,\n values,\n };\n}\n\nfunction getDisplayText(mappedAnnotations, displaySet) {\n if (!mappedAnnotations || !mappedAnnotations.length) {\n return '';\n }\n\n const displayText = [];\n\n // Area is the same for all series\n const { angle, unit, SeriesNumber, SOPInstanceUID, frameNumber } = mappedAnnotations[0];\n\n const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);\n\n let InstanceNumber;\n if (instance) {\n InstanceNumber = instance.InstanceNumber;\n }\n\n const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';\n const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';\n if (angle === undefined) {\n return displayText;\n }\n const roundedAngle = utils.roundNumber(angle, 2);\n displayText.push(\n `${roundedAngle} ${getDisplayUnit(unit)} (S: ${SeriesNumber}${instanceText}${frameText})`\n );\n\n return displayText;\n}\n\nexport default Angle;\n","import SUPPORTED_TOOLS from './constants/supportedTools';\nimport getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';\n\nconst PlanarFreehandROI = {\n toAnnotation: measurement => {},\n\n /**\n * Maps cornerstone annotation event data to measurement service format.\n *\n * @param {Object} cornerstone Cornerstone event data\n * @return {Measurement} Measurement instance\n */\n toMeasurement: (\n csToolsEventDetail,\n DisplaySetService,\n CornerstoneViewportService,\n getValueTypeFromToolType\n ) => {\n const { annotation, viewportId } = csToolsEventDetail;\n const { metadata, data, annotationUID } = annotation;\n\n if (!metadata || !data) {\n console.warn('PlanarFreehandROI tool: Missing metadata or data');\n return null;\n }\n\n const { toolName, referencedImageId, FrameOfReferenceUID } = metadata;\n const validToolType = SUPPORTED_TOOLS.includes(toolName);\n\n if (!validToolType) {\n throw new Error('Tool not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(\n referencedImageId,\n CornerstoneViewportService,\n viewportId\n );\n\n let displaySet;\n\n if (SOPInstanceUID) {\n displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID\n );\n } else {\n displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID);\n }\n\n const { points } = data.handles;\n\n const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);\n\n const displayText = getDisplayText(mappedAnnotations);\n const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);\n\n return {\n uid: annotationUID,\n SOPInstanceUID,\n FrameOfReferenceUID,\n points,\n metadata,\n referenceSeriesUID: SeriesInstanceUID,\n referenceStudyUID: StudyInstanceUID,\n toolName: metadata.toolName,\n displaySetInstanceUID: displaySet.displaySetInstanceUID,\n label: data.label,\n displayText: displayText,\n data: { ...data, ...data.cachedStats },\n type: getValueTypeFromToolType(toolName),\n getReport,\n };\n },\n};\n\n/**\n * It maps an imaging library annotation to a list of simplified annotation properties.\n *\n * @param {Object} annotationData\n * @param {Object} DisplaySetService\n * @returns\n */\nfunction getMappedAnnotations(annotationData, DisplaySetService) {\n const { metadata, data } = annotationData;\n const { label } = data;\n const { referencedImageId } = metadata;\n\n const annotations = [];\n\n const { SOPInstanceUID: _SOPInstanceUID, SeriesInstanceUID: _SeriesInstanceUID } =\n getSOPInstanceAttributes(referencedImageId) || {};\n\n if (!_SOPInstanceUID || !_SeriesInstanceUID) {\n return annotations;\n }\n\n const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(\n _SOPInstanceUID,\n _SeriesInstanceUID\n );\n\n const { SeriesNumber, SeriesInstanceUID } = displaySet;\n\n annotations.push({\n SeriesInstanceUID,\n SeriesNumber,\n label,\n data,\n });\n\n return annotations;\n}\n\n/**\n * TBD\n * This function is used to convert the measurement data to a format that is suitable for the report generation (e.g. for the csv report).\n * The report returns a list of columns and corresponding values.\n * @param {*} mappedAnnotations\n * @param {*} points\n * @param {*} FrameOfReferenceUID\n * @returns Object representing the report's content for this tool.\n */\nfunction _getReport(mappedAnnotations, points, FrameOfReferenceUID) {\n const columns = [];\n const values = [];\n\n return {\n columns,\n values,\n };\n}\n\nfunction getDisplayText(mappedAnnotations) {\n return '';\n}\n\nexport default PlanarFreehandROI;\n","import SUPPORTED_TOOLS from './constants/supportedTools';\nimport { getDisplayUnit } from './utils';\nimport getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';\nimport { utils } from '@ohif/core';\n\nconst RectangleROI = {\n toAnnotation: measurement => {},\n toMeasurement: (\n csToolsEventDetail,\n DisplaySetService,\n CornerstoneViewportService,\n getValueTypeFromToolType\n ) => {\n const { annotation, viewportId } = csToolsEventDetail;\n const { metadata, data, annotationUID } = annotation;\n\n if (!metadata || !data) {\n console.warn('Rectangle ROI tool: Missing metadata or data');\n return null;\n }\n\n const { toolName, referencedImageId, FrameOfReferenceUID } = metadata;\n const validToolType = SUPPORTED_TOOLS.includes(toolName);\n\n if (!validToolType) {\n throw new Error('Tool not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(\n referencedImageId,\n CornerstoneViewportService,\n viewportId\n );\n\n let displaySet;\n\n if (SOPInstanceUID) {\n displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID\n );\n } else {\n displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID);\n }\n\n const { points } = data.handles;\n\n const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);\n\n const displayText = getDisplayText(mappedAnnotations, displaySet);\n const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);\n\n return {\n uid: annotationUID,\n SOPInstanceUID,\n FrameOfReferenceUID,\n points,\n metadata,\n referenceSeriesUID: SeriesInstanceUID,\n referenceStudyUID: StudyInstanceUID,\n frameNumber: mappedAnnotations[0]?.frameNumber || 1,\n toolName: metadata.toolName,\n displaySetInstanceUID: displaySet.displaySetInstanceUID,\n label: data.label,\n displayText: displayText,\n data: data.cachedStats,\n type: getValueTypeFromToolType(toolName),\n getReport,\n };\n },\n};\n\nfunction getMappedAnnotations(annotation, DisplaySetService) {\n const { metadata, data } = annotation;\n const { cachedStats } = data;\n const { referencedImageId } = metadata;\n const targets = Object.keys(cachedStats);\n\n if (!targets.length) {\n return [];\n }\n\n const annotations = [];\n Object.keys(cachedStats).forEach(targetId => {\n const targetStats = cachedStats[targetId];\n\n if (!referencedImageId) {\n // Todo: Non-acquisition plane measurement mapping not supported yet\n throw new Error('Non-acquisition plane measurement mapping not supported');\n }\n\n const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =\n getSOPInstanceAttributes(referencedImageId);\n\n const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(\n SOPInstanceUID,\n SeriesInstanceUID,\n frameNumber\n );\n\n const { SeriesNumber } = displaySet;\n const { mean, stdDev, max, area, Modality, modalityUnit, areaUnit } = targetStats;\n\n annotations.push({\n SeriesInstanceUID,\n SOPInstanceUID,\n SeriesNumber,\n frameNumber,\n Modality,\n unit: modalityUnit,\n mean,\n stdDev,\n max,\n area,\n areaUnit,\n });\n });\n\n return annotations;\n}\n\n/*\nThis function is used to convert the measurement data to a format that is\nsuitable for the report generation (e.g. for the csv report). The report\nreturns a list of columns and corresponding values.\n*/\nfunction _getReport(mappedAnnotations, points, FrameOfReferenceUID) {\n const columns = [];\n const values = [];\n\n // Add Type\n columns.push('AnnotationType');\n values.push('Cornerstone:RectangleROI');\n\n mappedAnnotations.forEach(annotation => {\n const { mean, stdDev, max, area, unit, areaUnit } = annotation;\n\n if (!mean || !unit || !max || !area) {\n return;\n }\n\n columns.push(`Maximum`, `Mean`, `Std Dev`, 'Pixel Unit', `Area`, 'Unit');\n values.push(max, mean, stdDev, unit, area, areaUnit);\n });\n\n if (FrameOfReferenceUID) {\n columns.push('FrameOfReferenceUID');\n values.push(FrameOfReferenceUID);\n }\n\n if (points) {\n columns.push('points');\n // points has the form of [[x1, y1, z1], [x2, y2, z2], ...]\n // convert it to string of [[x1 y1 z1];[x2 y2 z2];...]\n // so that it can be used in the csv report\n values.push(points.map(p => p.join(' ')).join(';'));\n }\n\n return {\n columns,\n values,\n };\n}\n\nfunction getDisplayText(mappedAnnotations, displaySet) {\n if (!mappedAnnotations || !mappedAnnotations.length) {\n return '';\n }\n\n const displayText = [];\n\n // Area is the same for all series\n const { area, SOPInstanceUID, frameNumber, areaUnit } = mappedAnnotations[0];\n\n const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);\n\n let InstanceNumber;\n if (instance) {\n InstanceNumber = instance.InstanceNumber;\n }\n\n const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';\n const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';\n\n // Area sometimes becomes undefined if `preventHandleOutsideImage` is off.\n const roundedArea = utils.roundNumber(area || 0, 2);\n displayText.push(`${roundedArea} ${getDisplayUnit(areaUnit)}`);\n\n // Todo: we need a better UI for displaying all these information\n mappedAnnotations.forEach(mappedAnnotation => {\n const { unit, max, SeriesNumber } = mappedAnnotation;\n\n let maxStr = '';\n if (max) {\n const roundedMax = utils.roundNumber(max, 2);\n maxStr = `Max: ${roundedMax} ${getDisplayUnit(unit)} `;\n }\n\n const str = `${maxStr}(S:${SeriesNumber}${instanceText}${frameText})`;\n if (!displayText.includes(str)) {\n displayText.push(str);\n }\n });\n\n return displayText;\n}\n\nexport default RectangleROI;\n","import { MeasurementService } from '@ohif/core';\nimport Length from './Length';\nimport Bidirectional from './Bidirectional';\nimport EllipticalROI from './EllipticalROI';\nimport CircleROI from './CircleROI';\nimport ArrowAnnotate from './ArrowAnnotate';\nimport CobbAngle from './CobbAngle';\nimport Angle from './Angle';\nimport PlanarFreehandROI from './PlanarFreehandROI';\nimport RectangleROI from './RectangleROI';\n\nconst measurementServiceMappingsFactory = (\n measurementService: MeasurementService,\n displaySetService,\n cornerstoneViewportService\n) => {\n /**\n * Maps measurement service format object to cornerstone annotation object.\n *\n * @param measurement The measurement instance\n * @param definition The source definition\n * @return Cornerstone annotation data\n */\n\n const _getValueTypeFromToolType = toolType => {\n const { POLYLINE, ELLIPSE, CIRCLE, RECTANGLE, BIDIRECTIONAL, POINT, ANGLE } =\n MeasurementService.VALUE_TYPES;\n\n // TODO -> I get why this was attempted, but its not nearly flexible enough.\n // A single measurement may have an ellipse + a bidirectional measurement, for instances.\n // You can't define a bidirectional tool as a single type..\n const TOOL_TYPE_TO_VALUE_TYPE = {\n Length: POLYLINE,\n EllipticalROI: ELLIPSE,\n CircleROI: CIRCLE,\n RectangleROI: RECTANGLE,\n PlanarFreehandROI: POLYLINE,\n Bidirectional: BIDIRECTIONAL,\n ArrowAnnotate: POINT,\n CobbAngle: ANGLE,\n Angle: ANGLE,\n };\n\n return TOOL_TYPE_TO_VALUE_TYPE[toolType];\n };\n\n const factories = {\n Length: {\n toAnnotation: Length.toAnnotation,\n toMeasurement: csToolsAnnotation =>\n Length.toMeasurement(\n csToolsAnnotation,\n displaySetService,\n cornerstoneViewportService,\n _getValueTypeFromToolType\n ),\n matchingCriteria: [\n {\n valueType: MeasurementService.VALUE_TYPES.POLYLINE,\n points: 2,\n },\n ],\n },\n Bidirectional: {\n toAnnotation: Bidirectional.toAnnotation,\n toMeasurement: csToolsAnnotation =>\n Bidirectional.toMeasurement(\n csToolsAnnotation,\n displaySetService,\n cornerstoneViewportService,\n _getValueTypeFromToolType\n ),\n matchingCriteria: [\n // TODO -> We should eventually do something like shortAxis + longAxis,\n // But its still a little unclear how these automatic interpretations will work.\n {\n valueType: MeasurementService.VALUE_TYPES.POLYLINE,\n points: 2,\n },\n {\n valueType: MeasurementService.VALUE_TYPES.POLYLINE,\n points: 2,\n },\n ],\n },\n\n EllipticalROI: {\n toAnnotation: EllipticalROI.toAnnotation,\n toMeasurement: csToolsAnnotation =>\n EllipticalROI.toMeasurement(\n csToolsAnnotation,\n displaySetService,\n cornerstoneViewportService,\n _getValueTypeFromToolType\n ),\n matchingCriteria: [\n {\n valueType: MeasurementService.VALUE_TYPES.ELLIPSE,\n },\n ],\n },\n\n CircleROI: {\n toAnnotation: CircleROI.toAnnotation,\n toMeasurement: csToolsAnnotation =>\n CircleROI.toMeasurement(\n csToolsAnnotation,\n displaySetService,\n cornerstoneViewportService,\n _getValueTypeFromToolType\n ),\n matchingCriteria: [\n {\n valueType: MeasurementService.VALUE_TYPES.CIRCLE,\n },\n ],\n },\n\n RectangleROI: {\n toAnnotation: RectangleROI.toAnnotation,\n toMeasurement: csToolsAnnotation =>\n RectangleROI.toMeasurement(\n csToolsAnnotation,\n displaySetService,\n cornerstoneViewportService,\n _getValueTypeFromToolType\n ),\n matchingCriteria: [\n {\n valueType: MeasurementService.VALUE_TYPES.POLYLINE,\n },\n ],\n },\n\n PlanarFreehandROI: {\n toAnnotation: PlanarFreehandROI.toAnnotation,\n toMeasurement: csToolsAnnotation =>\n PlanarFreehandROI.toMeasurement(\n csToolsAnnotation,\n displaySetService,\n cornerstoneViewportService,\n _getValueTypeFromToolType\n ),\n matchingCriteria: [\n {\n valueType: MeasurementService.VALUE_TYPES.POLYLINE,\n },\n ],\n },\n\n ArrowAnnotate: {\n toAnnotation: ArrowAnnotate.toAnnotation,\n toMeasurement: csToolsAnnotation =>\n ArrowAnnotate.toMeasurement(\n csToolsAnnotation,\n displaySetService,\n cornerstoneViewportService,\n _getValueTypeFromToolType\n ),\n matchingCriteria: [\n {\n valueType: MeasurementService.VALUE_TYPES.POINT,\n points: 1,\n },\n ],\n },\n\n CobbAngle: {\n toAnnotation: CobbAngle.toAnnotation,\n toMeasurement: csToolsAnnotation =>\n CobbAngle.toMeasurement(\n csToolsAnnotation,\n displaySetService,\n cornerstoneViewportService,\n _getValueTypeFromToolType\n ),\n matchingCriteria: [\n {\n valueType: MeasurementService.VALUE_TYPES.ANGLE,\n },\n ],\n },\n\n Angle: {\n toAnnotation: Angle.toAnnotation,\n toMeasurement: csToolsAnnotation =>\n Angle.toMeasurement(\n csToolsAnnotation,\n displaySetService,\n cornerstoneViewportService,\n _getValueTypeFromToolType\n ),\n matchingCriteria: [\n {\n valueType: MeasurementService.VALUE_TYPES.ANGLE,\n },\n ],\n },\n };\n\n return factories;\n};\n\nexport default measurementServiceMappingsFactory;\n","import { eventTarget } from '@cornerstonejs/core';\nimport { Enums, annotation } from '@cornerstonejs/tools';\nimport { DicomMetadataStore } from '@ohif/core';\nimport { toolNames } from './initCornerstoneTools';\nimport { onCompletedCalibrationLine } from './tools/CalibrationLineTool';\n\nimport measurementServiceMappingsFactory from './utils/measurementServiceMappings/measurementServiceMappingsFactory';\nimport getSOPInstanceAttributes from './utils/measurementServiceMappings/utils/getSOPInstanceAttributes';\n\nconst { removeAnnotation } = annotation.state;\n\nconst csToolsEvents = Enums.Events;\n\nconst CORNERSTONE_3D_TOOLS_SOURCE_NAME = 'Cornerstone3DTools';\nconst CORNERSTONE_3D_TOOLS_SOURCE_VERSION = '0.1';\n\nconst initMeasurementService = (\n measurementService,\n displaySetService,\n cornerstoneViewportService\n) => {\n /* Initialization */\n const {\n Length,\n Bidirectional,\n EllipticalROI,\n CircleROI,\n ArrowAnnotate,\n Angle,\n CobbAngle,\n RectangleROI,\n PlanarFreehandROI,\n } = measurementServiceMappingsFactory(\n measurementService,\n displaySetService,\n cornerstoneViewportService\n );\n const csTools3DVer1MeasurementSource = measurementService.createSource(\n CORNERSTONE_3D_TOOLS_SOURCE_NAME,\n CORNERSTONE_3D_TOOLS_SOURCE_VERSION\n );\n\n /* Mappings */\n measurementService.addMapping(\n csTools3DVer1MeasurementSource,\n 'Length',\n Length.matchingCriteria,\n Length.toAnnotation,\n Length.toMeasurement\n );\n\n measurementService.addMapping(\n csTools3DVer1MeasurementSource,\n 'Bidirectional',\n Bidirectional.matchingCriteria,\n Bidirectional.toAnnotation,\n Bidirectional.toMeasurement\n );\n\n measurementService.addMapping(\n csTools3DVer1MeasurementSource,\n 'EllipticalROI',\n EllipticalROI.matchingCriteria,\n EllipticalROI.toAnnotation,\n EllipticalROI.toMeasurement\n );\n\n measurementService.addMapping(\n csTools3DVer1MeasurementSource,\n 'CircleROI',\n CircleROI.matchingCriteria,\n CircleROI.toAnnotation,\n CircleROI.toMeasurement\n );\n\n measurementService.addMapping(\n csTools3DVer1MeasurementSource,\n 'ArrowAnnotate',\n ArrowAnnotate.matchingCriteria,\n ArrowAnnotate.toAnnotation,\n ArrowAnnotate.toMeasurement\n );\n\n measurementService.addMapping(\n csTools3DVer1MeasurementSource,\n 'CobbAngle',\n CobbAngle.matchingCriteria,\n CobbAngle.toAnnotation,\n CobbAngle.toMeasurement\n );\n\n measurementService.addMapping(\n csTools3DVer1MeasurementSource,\n 'Angle',\n Angle.matchingCriteria,\n Angle.toAnnotation,\n Angle.toMeasurement\n );\n\n measurementService.addMapping(\n csTools3DVer1MeasurementSource,\n 'RectangleROI',\n RectangleROI.matchingCriteria,\n RectangleROI.toAnnotation,\n RectangleROI.toMeasurement\n );\n\n measurementService.addMapping(\n csTools3DVer1MeasurementSource,\n 'PlanarFreehandROI',\n PlanarFreehandROI.matchingCriteria,\n PlanarFreehandROI.toAnnotation,\n PlanarFreehandROI.toMeasurement\n );\n\n // On the UI side, the Calibration Line tool will work almost the same as the\n // Length tool\n measurementService.addMapping(\n csTools3DVer1MeasurementSource,\n 'CalibrationLine',\n Length.matchingCriteria,\n Length.toAnnotation,\n Length.toMeasurement\n );\n\n return csTools3DVer1MeasurementSource;\n};\n\nconst connectToolsToMeasurementService = servicesManager => {\n const { measurementService, displaySetService, cornerstoneViewportService } =\n servicesManager.services;\n const csTools3DVer1MeasurementSource = initMeasurementService(\n measurementService,\n displaySetService,\n cornerstoneViewportService\n );\n connectMeasurementServiceToTools(\n measurementService,\n cornerstoneViewportService,\n csTools3DVer1MeasurementSource\n );\n const { annotationToMeasurement, remove } = csTools3DVer1MeasurementSource;\n\n //\n function addMeasurement(csToolsEvent) {\n try {\n const annotationAddedEventDetail = csToolsEvent.detail;\n const {\n annotation: { metadata, annotationUID },\n } = annotationAddedEventDetail;\n const { toolName } = metadata;\n\n if (csToolsEvent.type === completedEvt && toolName === toolNames.CalibrationLine) {\n // show modal to input the measurement (mm)\n onCompletedCalibrationLine(servicesManager, csToolsEvent)\n .then(\n () => {\n console.log('calibration applied');\n },\n () => true\n )\n .finally(() => {\n // we don't need the calibration line lingering around, remove the\n // annotation from the display\n removeAnnotation(annotationUID);\n removeMeasurement(csToolsEvent);\n // this will ensure redrawing of annotations\n cornerstoneViewportService.resize();\n });\n } else {\n // To force the measurementUID be the same as the annotationUID\n // Todo: this should be changed when a measurement can include multiple annotations\n // in the future\n annotationAddedEventDetail.uid = annotationUID;\n annotationToMeasurement(toolName, annotationAddedEventDetail);\n }\n } catch (error) {\n console.warn('Failed to update measurement:', error);\n }\n }\n\n function updateMeasurement(csToolsEvent) {\n try {\n const annotationModifiedEventDetail = csToolsEvent.detail;\n\n const {\n annotation: { metadata, annotationUID },\n } = annotationModifiedEventDetail;\n\n // If the measurement hasn't been added, don't modify it\n const measurement = measurementService.getMeasurement(annotationUID);\n\n if (!measurement) {\n return;\n }\n const { toolName } = metadata;\n\n annotationModifiedEventDetail.uid = annotationUID;\n // Passing true to indicate this is an update and NOT a annotation (start) completion.\n annotationToMeasurement(toolName, annotationModifiedEventDetail, true);\n } catch (error) {\n console.warn('Failed to update measurement:', error);\n }\n }\n function selectMeasurement(csToolsEvent) {\n try {\n const annotationSelectionEventDetail = csToolsEvent.detail;\n\n const { added: addedSelectedAnnotationUIDs, removed: removedSelectedAnnotationUIDs } =\n annotationSelectionEventDetail;\n\n if (removedSelectedAnnotationUIDs) {\n removedSelectedAnnotationUIDs.forEach(annotationUID =>\n measurementService.setMeasurementSelected(annotationUID, false)\n );\n }\n\n if (addedSelectedAnnotationUIDs) {\n addedSelectedAnnotationUIDs.forEach(annotationUID =>\n measurementService.setMeasurementSelected(annotationUID, true)\n );\n }\n } catch (error) {\n console.warn('Failed to select and unselect measurements:', error);\n }\n }\n\n /**\n * When csTools fires a removed event, remove the same measurement\n * from the measurement service\n *\n * @param {*} csToolsEvent\n */\n function removeMeasurement(csToolsEvent) {\n try {\n try {\n const annotationRemovedEventDetail = csToolsEvent.detail;\n const {\n annotation: { annotationUID },\n } = annotationRemovedEventDetail;\n\n const measurement = measurementService.getMeasurement(annotationUID);\n\n if (measurement) {\n console.log('~~ removeEvt', csToolsEvent);\n remove(annotationUID, annotationRemovedEventDetail);\n }\n } catch (error) {\n console.warn('Failed to update measurement:', error);\n }\n } catch (error) {\n console.warn('Failed to remove measurement:', error);\n }\n }\n\n // on display sets added, check if there are any measurements in measurement service that need to be\n // put into cornerstone tools\n const addedEvt = csToolsEvents.ANNOTATION_ADDED;\n const completedEvt = csToolsEvents.ANNOTATION_COMPLETED;\n const updatedEvt = csToolsEvents.ANNOTATION_MODIFIED;\n const removedEvt = csToolsEvents.ANNOTATION_REMOVED;\n const selectionEvt = csToolsEvents.ANNOTATION_SELECTION_CHANGE;\n\n eventTarget.addEventListener(addedEvt, addMeasurement);\n eventTarget.addEventListener(completedEvt, addMeasurement);\n eventTarget.addEventListener(updatedEvt, updateMeasurement);\n eventTarget.addEventListener(removedEvt, removeMeasurement);\n eventTarget.addEventListener(selectionEvt, selectMeasurement);\n\n return csTools3DVer1MeasurementSource;\n};\n\nconst connectMeasurementServiceToTools = (\n measurementService,\n cornerstoneViewportService,\n measurementSource\n) => {\n const { MEASUREMENT_REMOVED, MEASUREMENTS_CLEARED, MEASUREMENT_UPDATED, RAW_MEASUREMENT_ADDED } =\n measurementService.EVENTS;\n\n const csTools3DVer1MeasurementSource = measurementService.getSource(\n CORNERSTONE_3D_TOOLS_SOURCE_NAME,\n CORNERSTONE_3D_TOOLS_SOURCE_VERSION\n );\n\n measurementService.subscribe(MEASUREMENTS_CLEARED, ({ measurements }) => {\n if (!Object.keys(measurements).length) {\n return;\n }\n\n for (const measurement of Object.values(measurements)) {\n const { uid, source } = measurement;\n if (source.name !== CORNERSTONE_3D_TOOLS_SOURCE_NAME) {\n continue;\n }\n\n removeAnnotation(uid);\n }\n });\n\n measurementService.subscribe(\n MEASUREMENT_UPDATED,\n ({ source, measurement, notYetUpdatedAtSource }) => {\n if (source.name !== CORNERSTONE_3D_TOOLS_SOURCE_NAME) {\n return;\n }\n\n if (notYetUpdatedAtSource === false) {\n // This event was fired by cornerstone telling the measurement service to sync.\n // Already in sync.\n return;\n }\n\n const { uid, label } = measurement;\n\n const sourceAnnotation = annotation.state.getAnnotation(uid);\n const { data, metadata } = sourceAnnotation;\n\n if (!data) {\n return;\n }\n\n if (data.label !== label) {\n data.label = label;\n }\n\n if (metadata.toolName === 'ArrowAnnotate') {\n data.text = label;\n }\n\n // Todo: trigger render for annotation\n }\n );\n\n measurementService.subscribe(\n RAW_MEASUREMENT_ADDED,\n ({ source, measurement, data, dataSource }) => {\n if (source.name !== CORNERSTONE_3D_TOOLS_SOURCE_NAME) {\n return;\n }\n\n const { referenceSeriesUID, referenceStudyUID, SOPInstanceUID } = measurement;\n\n const instance = DicomMetadataStore.getInstance(\n referenceStudyUID,\n referenceSeriesUID,\n SOPInstanceUID\n );\n\n let imageId;\n let frameNumber = 1;\n\n if (measurement?.metadata?.referencedImageId) {\n imageId = measurement.metadata.referencedImageId;\n frameNumber = getSOPInstanceAttributes(measurement.metadata.referencedImageId).frameNumber;\n } else {\n imageId = dataSource.getImageIdsForInstance({ instance });\n }\n\n const annotationManager = annotation.state.getAnnotationManager();\n annotationManager.addAnnotation({\n annotationUID: measurement.uid,\n highlighted: false,\n isLocked: false,\n invalidated: false,\n metadata: {\n toolName: measurement.toolName,\n FrameOfReferenceUID: measurement.FrameOfReferenceUID,\n referencedImageId: imageId,\n },\n data: {\n text: data.annotation.data.text,\n handles: { ...data.annotation.data.handles },\n cachedStats: { ...data.annotation.data.cachedStats },\n label: data.annotation.data.label,\n frameNumber: frameNumber,\n },\n });\n }\n );\n\n measurementService.subscribe(\n MEASUREMENT_REMOVED,\n ({ source, measurement: removedMeasurementId }) => {\n if (source?.name && source.name !== CORNERSTONE_3D_TOOLS_SOURCE_NAME) {\n return;\n }\n removeAnnotation(removedMeasurementId);\n const renderingEngine = cornerstoneViewportService.getRenderingEngine();\n // Note: We could do a better job by triggering the render on the\n // viewport itself, but the removeAnnotation does not include that info...\n renderingEngine.render();\n }\n );\n};\n\nexport {\n initMeasurementService,\n connectToolsToMeasurementService,\n connectMeasurementServiceToTools,\n};\n","import { utilities } from '@cornerstonejs/tools';\n\nfunction initCineService(cineService) {\n const playClip = (element, playClipOptions) => {\n return utilities.cine.playClip(element, playClipOptions);\n };\n\n const stopClip = element => {\n return utilities.cine.stopClip(element);\n };\n\n cineService.setServiceImplementation({ playClip, stopClip });\n}\n\nexport default initCineService;\n","import { cache, imageLoadPoolManager, Enums } from '@cornerstonejs/core';\nimport getInterleavedFrames from './getInterleavedFrames';\nimport { compact, flatten, zip } from 'lodash';\n\n// Map of volumeId and SeriesInstanceId\nconst volumeIdMapsToLoad = new Map();\nconst viewportIdVolumeInputArrayMap = new Map();\n\n/**\n * This function caches the volumeUIDs until all the volumes inside the\n * hanging protocol are initialized. Then it goes through the imageIds\n * of the volumes, and interleave them, in order for the volumes to be loaded\n * together from middle to the start and the end.\n * @param {Object} props image loading properties from Cornerstone ViewportService\n * @returns\n */\nexport default function interleaveCenterLoader({\n data: { viewportId, volumeInputArray },\n displaySetsMatchDetails,\n viewportMatchDetails: matchDetails,\n}) {\n viewportIdVolumeInputArrayMap.set(viewportId, volumeInputArray);\n\n // Based on the volumeInputs store the volumeIds and SeriesInstanceIds\n // to keep track of the volumes being loaded\n for (const volumeInput of volumeInputArray) {\n const { volumeId } = volumeInput;\n const volume = cache.getVolume(volumeId);\n\n if (!volume) {\n return;\n }\n\n // if the volumeUID is not in the volumeUIDs array, add it\n if (!volumeIdMapsToLoad.has(volumeId)) {\n const { metadata } = volume;\n volumeIdMapsToLoad.set(volumeId, metadata.SeriesInstanceUID);\n }\n }\n\n /**\n * The following is checking if all the viewports that were matched in the HP has been\n * successfully created their cornerstone viewport or not. Todo: This can be\n * improved by not checking it, and as soon as the matched DisplaySets have their\n * volume loaded, we start the loading, but that comes at the cost of viewports\n * not being created yet (e.g., in a 10 viewport ptCT fusion, when one ct viewport and one\n * pt viewport are created we have a guarantee that the volumes are created in the cache\n * but the rest of the viewports (fusion, mip etc.) are not created yet. So\n * we can't initiate setting the volumes for those viewports. One solution can be\n * to add an event when a viewport is created (not enabled element event) and then\n * listen to it and as the other viewports are created we can set the volumes for them\n * since volumes are already started loading.\n */\n if (matchDetails.size !== viewportIdVolumeInputArrayMap.size) {\n return;\n }\n\n // Check if all the matched volumes are loaded\n for (const [_, details] of displaySetsMatchDetails.entries()) {\n const { SeriesInstanceUID } = details;\n\n // HangingProtocol has matched, but don't have all the volumes created yet, so return\n if (!Array.from(volumeIdMapsToLoad.values()).includes(SeriesInstanceUID)) {\n return;\n }\n }\n\n const volumeIds = Array.from(volumeIdMapsToLoad.keys()).slice();\n // get volumes from cache\n const volumes = volumeIds.map(volumeId => {\n return cache.getVolume(volumeId);\n });\n\n // iterate over all volumes, and get their imageIds, and interleave\n // the imageIds and save them in AllRequests for later use\n const AllRequests = [];\n volumes.forEach(volume => {\n const requests = volume.getImageLoadRequests();\n\n if (!requests.length || !requests[0] || !requests[0].imageId) {\n return;\n }\n\n const requestImageIds = requests.map(request => {\n return request.imageId;\n });\n\n const imageIds = getInterleavedFrames(requestImageIds);\n\n const reOrderedRequests = imageIds.map(({ imageId }) => {\n const request = requests.find(req => req.imageId === imageId);\n return request;\n });\n\n AllRequests.push(reOrderedRequests);\n });\n\n // flatten the AllRequests array, which will result in a list of all the\n // imageIds for all the volumes but interleaved\n const interleavedRequests = compact(flatten(zip(...AllRequests)));\n\n // set the finalRequests to the imageLoadPoolManager\n const finalRequests = [];\n interleavedRequests.forEach(request => {\n const { imageId } = request;\n\n AllRequests.forEach(volumeRequests => {\n const volumeImageIdRequest = volumeRequests.find(req => req.imageId === imageId);\n if (volumeImageIdRequest) {\n finalRequests.push(volumeImageIdRequest);\n }\n });\n });\n\n const requestType = Enums.RequestType.Prefetch;\n const priority = 0;\n\n finalRequests.forEach(({ callLoadImage, additionalDetails, imageId, imageIdIndex, options }) => {\n const callLoadImageBound = callLoadImage.bind(null, imageId, imageIdIndex, options);\n\n imageLoadPoolManager.addRequest(callLoadImageBound, requestType, additionalDetails, priority);\n });\n\n // clear the volumeIdMapsToLoad\n volumeIdMapsToLoad.clear();\n\n // copy the viewportIdVolumeInputArrayMap\n const viewportIdVolumeInputArrayMapCopy = new Map(viewportIdVolumeInputArrayMap);\n\n // reset the viewportIdVolumeInputArrayMap\n viewportIdVolumeInputArrayMap.clear();\n\n return viewportIdVolumeInputArrayMapCopy;\n}\n","export default function getInterleavedFrames(imageIds) {\n const minImageIdIndex = 0;\n const maxImageIdIndex = imageIds.length - 1;\n\n const middleImageIdIndex = Math.floor(imageIds.length / 2);\n\n let lowerImageIdIndex = middleImageIdIndex;\n let upperImageIdIndex = middleImageIdIndex;\n\n // Build up an array of images to prefetch, starting with the current image.\n const imageIdsToPrefetch = [\n { imageId: imageIds[middleImageIdIndex], imageIdIndex: middleImageIdIndex },\n ];\n\n const prefetchQueuedFilled = {\n currentPositionDownToMinimum: false,\n currentPositionUpToMaximum: false,\n };\n\n // Check if on edges and some criteria is already fulfilled\n\n if (middleImageIdIndex === minImageIdIndex) {\n prefetchQueuedFilled.currentPositionDownToMinimum = true;\n } else if (middleImageIdIndex === maxImageIdIndex) {\n prefetchQueuedFilled.currentPositionUpToMaximum = true;\n }\n\n while (\n !prefetchQueuedFilled.currentPositionDownToMinimum ||\n !prefetchQueuedFilled.currentPositionUpToMaximum\n ) {\n if (!prefetchQueuedFilled.currentPositionDownToMinimum) {\n // Add imageId below\n lowerImageIdIndex--;\n imageIdsToPrefetch.push({\n imageId: imageIds[lowerImageIdIndex],\n imageIdIndex: lowerImageIdIndex,\n });\n\n if (lowerImageIdIndex === minImageIdIndex) {\n prefetchQueuedFilled.currentPositionDownToMinimum = true;\n }\n }\n\n if (!prefetchQueuedFilled.currentPositionUpToMaximum) {\n // Add imageId above\n upperImageIdIndex++;\n imageIdsToPrefetch.push({\n imageId: imageIds[upperImageIdIndex],\n imageIdIndex: upperImageIdIndex,\n });\n\n if (upperImageIdIndex === maxImageIdIndex) {\n prefetchQueuedFilled.currentPositionUpToMaximum = true;\n }\n }\n }\n\n return imageIdsToPrefetch;\n}\n","import { cache, imageLoadPoolManager, Enums } from '@cornerstonejs/core';\nimport getNthFrames from './getNthFrames';\nimport interleave from './interleave';\n\n// Map of volumeId and SeriesInstanceId\nconst volumeIdMapsToLoad = new Map();\nconst viewportIdVolumeInputArrayMap = new Map();\n\n/**\n * This function caches the volumeUIDs until all the volumes inside the\n * hanging protocol are initialized. Then it goes through the requests and\n * chooses a sub-selection starting the the first few objects, center objects\n * and last objects, and then the remaining nth images until all instances are\n * retrieved. This causes the image to have a progressive load order and looks\n * visually much better.\n * @param {Object} props image loading properties from Cornerstone ViewportService\n */\nexport default function interleaveNthLoader({\n data: { viewportId, volumeInputArray },\n displaySetsMatchDetails,\n}) {\n viewportIdVolumeInputArrayMap.set(viewportId, volumeInputArray);\n\n // Based on the volumeInputs store the volumeIds and SeriesInstanceIds\n // to keep track of the volumes being loaded\n for (const volumeInput of volumeInputArray) {\n const { volumeId } = volumeInput;\n const volume = cache.getVolume(volumeId);\n\n if (!volume) {\n console.log(\"interleaveNthLoader::No volume, can't load it\");\n return;\n }\n\n // if the volumeUID is not in the volumeUIDs array, add it\n if (!volumeIdMapsToLoad.has(volumeId)) {\n const { metadata } = volume;\n volumeIdMapsToLoad.set(volumeId, metadata.SeriesInstanceUID);\n }\n }\n\n const volumeIds = Array.from(volumeIdMapsToLoad.keys()).slice();\n // get volumes from cache\n const volumes = volumeIds.map(volumeId => {\n return cache.getVolume(volumeId);\n });\n\n // iterate over all volumes, and get their imageIds, and interleave\n // the imageIds and save them in AllRequests for later use\n const originalRequests = volumes\n .map(volume => volume.getImageLoadRequests())\n .filter(requests => requests?.[0]?.imageId);\n\n const orderedRequests = originalRequests.map(request => getNthFrames(request));\n\n // set the finalRequests to the imageLoadPoolManager\n const finalRequests = interleave(orderedRequests);\n\n const requestType = Enums.RequestType.Prefetch;\n const priority = 0;\n\n finalRequests.forEach(({ callLoadImage, additionalDetails, imageId, imageIdIndex, options }) => {\n const callLoadImageBound = callLoadImage.bind(null, imageId, imageIdIndex, options);\n\n imageLoadPoolManager.addRequest(callLoadImageBound, requestType, additionalDetails, priority);\n });\n\n // clear the volumeIdMapsToLoad\n volumeIdMapsToLoad.clear();\n\n // copy the viewportIdVolumeInputArrayMap\n const viewportIdVolumeInputArrayMapCopy = new Map(viewportIdVolumeInputArrayMap);\n\n // reset the viewportIdVolumeInputArrayMap\n viewportIdVolumeInputArrayMap.clear();\n\n return viewportIdVolumeInputArrayMapCopy;\n}\n","/**\n * Interleave the items from all the lists so that the first items are first\n * in the returned list, the second items are next etc.\n * Does this in a O(n) fashion, and return lists[0] if there is only one list.\n *\n * @param {[]} lists\n * @returns [] reordered to be breadth first traversal of lists\n */\nexport default function interleave(lists) {\n if (!lists || !lists.length) {\n return [];\n }\n if (lists.length === 1) {\n return lists[0];\n }\n console.time('interleave');\n const useLists = [...lists];\n const ret = [];\n for (let i = 0; useLists.length > 0; i++) {\n for (const list of useLists) {\n if (i >= list.length) {\n useLists.splice(useLists.indexOf(list), 1);\n continue;\n }\n ret.push(list[i]);\n }\n }\n console.timeEnd('interleave');\n return ret;\n}\n","/**\n * Returns a re-ordered array consisting of, in order:\n * 1. First few objects\n * 2. Center objects\n * 3. Last few objects\n * 4. nth Objects (n=7), set 2\n * 5. nth Objects set 5,\n * 6. Remaining objects\n * What this does is return the first/center/start objects, as those\n * are often used first, then a selection of objects scattered over the\n * instances in order to allow making requests over a set of image instances.\n *\n * @param {[]} imageIds\n * @returns [] reordered to be an nth selection\n */\nexport default function getNthFrames(imageIds) {\n const frames = [[], [], [], [], []];\n const centerStart = imageIds.length / 2 - 3;\n const centerEnd = centerStart + 6;\n\n for (let i = 0; i < imageIds.length; i++) {\n if (i < 2 || i > imageIds.length - 4 || (i > centerStart && i < centerEnd)) {\n frames[0].push(imageIds[i]);\n } else if (i % 7 === 2) {\n frames[1].push(imageIds[i]);\n } else if (i % 7 === 5) {\n frames[2].push(imageIds[i]);\n } else {\n frames[(i % 2) + 3].push(imageIds[i]);\n }\n }\n const ret = [...frames[0], ...frames[1], ...frames[2], ...frames[3], ...frames[4]];\n return ret;\n}\n","import { cache, imageLoadPoolManager, Enums } from '@cornerstonejs/core';\nimport { compact, flatten, zip } from 'lodash';\n\n// Map of volumeId and SeriesInstanceId\nconst volumeIdMapsToLoad = new Map();\nconst viewportIdVolumeInputArrayMap = new Map();\n\n/**\n * This function caches the volumeIds until all the volumes inside the\n * hanging protocol are initialized. Then it goes through the imageIds\n * of the volumes, and interleave them, in order for the volumes to be loaded\n * together from middle to the start and the end.\n * @param {Object} {viewportData, displaySetMatchDetails}\n * @returns\n */\nexport default function interleaveTopToBottom({\n data: { viewportId, volumeInputArray },\n displaySetsMatchDetails,\n viewportMatchDetails: matchDetails,\n}) {\n viewportIdVolumeInputArrayMap.set(viewportId, volumeInputArray);\n\n // Based on the volumeInputs store the volumeIds and SeriesInstanceIds\n // to keep track of the volumes being loaded\n for (const volumeInput of volumeInputArray) {\n const { volumeId } = volumeInput;\n const volume = cache.getVolume(volumeId);\n\n if (!volume) {\n return;\n }\n\n // if the volumeUID is not in the volumeUIDs array, add it\n if (!volumeIdMapsToLoad.has(volumeId)) {\n const { metadata } = volume;\n volumeIdMapsToLoad.set(volumeId, metadata.SeriesInstanceUID);\n }\n }\n\n /**\n * The following is checking if all the viewports that were matched in the HP has been\n * successfully created their cornerstone viewport or not. Todo: This can be\n * improved by not checking it, and as soon as the matched DisplaySets have their\n * volume loaded, we start the loading, but that comes at the cost of viewports\n * not being created yet (e.g., in a 10 viewport ptCT fusion, when one ct viewport and one\n * pt viewport are created we have a guarantee that the volumes are created in the cache\n * but the rest of the viewports (fusion, mip etc.) are not created yet. So\n * we can't initiate setting the volumes for those viewports. One solution can be\n * to add an event when a viewport is created (not enabled element event) and then\n * listen to it and as the other viewports are created we can set the volumes for them\n * since volumes are already started loading.\n */\n if (matchDetails.size !== viewportIdVolumeInputArrayMap.size) {\n return;\n }\n\n // Check if all the matched volumes are loaded\n for (const [_, details] of displaySetsMatchDetails.entries()) {\n const { SeriesInstanceUID } = details;\n\n // HangingProtocol has matched, but don't have all the volumes created yet, so return\n if (!Array.from(volumeIdMapsToLoad.values()).includes(SeriesInstanceUID)) {\n return;\n }\n }\n\n const volumeIds = Array.from(volumeIdMapsToLoad.keys()).slice();\n // get volumes from cache\n const volumes = volumeIds.map(volumeId => {\n return cache.getVolume(volumeId);\n });\n\n // iterate over all volumes, and get their imageIds, and interleave\n // the imageIds and save them in AllRequests for later use\n const AllRequests = [];\n volumes.forEach(volume => {\n const requests = volume.getImageLoadRequests();\n\n if (!requests.length || !requests[0] || !requests[0].imageId) {\n return;\n }\n\n // reverse the requests\n AllRequests.push(requests.reverse());\n });\n\n // flatten the AllRequests array, which will result in a list of all the\n // imageIds for all the volumes but interleaved\n const interleavedRequests = compact(flatten(zip(...AllRequests)));\n\n // set the finalRequests to the imageLoadPoolManager\n const finalRequests = [];\n interleavedRequests.forEach(request => {\n const { imageId } = request;\n\n AllRequests.forEach(volumeRequests => {\n const volumeImageIdRequest = volumeRequests.find(req => req.imageId === imageId);\n if (volumeImageIdRequest) {\n finalRequests.push(volumeImageIdRequest);\n }\n });\n });\n\n const requestType = Enums.RequestType.Prefetch;\n const priority = 0;\n\n finalRequests.forEach(({ callLoadImage, additionalDetails, imageId, imageIdIndex, options }) => {\n const callLoadImageBound = callLoadImage.bind(null, imageId, imageIdIndex, options);\n\n imageLoadPoolManager.addRequest(callLoadImageBound, requestType, additionalDetails, priority);\n });\n\n // clear the volumeIdMapsToLoad\n volumeIdMapsToLoad.clear();\n\n // copy the viewportIdVolumeInputArrayMap\n const viewportIdVolumeInputArrayMapCopy = new Map(viewportIdVolumeInputArrayMap);\n\n // reset the viewportIdVolumeInputArrayMap\n viewportIdVolumeInputArrayMap.clear();\n\n return viewportIdVolumeInputArrayMapCopy;\n}\n","/**\n * Finds tool nearby event position triggered.\n *\n * @param {Object} commandsManager mannager of commands\n * @param {Object} event that has being triggered\n * @returns cs toolData or undefined if not found.\n */\nexport const findNearbyToolData = (commandsManager, evt) => {\n if (!evt?.detail) {\n return;\n }\n const { element, currentPoints } = evt.detail;\n return commandsManager.runCommand(\n 'getNearbyAnnotation',\n {\n element,\n canvasCoordinates: currentPoints?.canvas,\n },\n 'CORNERSTONE'\n );\n};\n","import { eventTarget, EVENTS } from '@cornerstonejs/core';\nimport { Enums } from '@cornerstonejs/tools';\nimport { setEnabledElement } from './state';\nimport { findNearbyToolData } from './utils/findNearbyToolData';\n\nconst cs3DToolsEvents = Enums.Events;\n\nconst DEFAULT_CONTEXT_MENU_CLICKS = {\n button1: {\n commands: [\n {\n commandName: 'closeContextMenu',\n },\n ],\n },\n button3: {\n commands: [\n {\n commandName: 'showCornerstoneContextMenu',\n commandOptions: {\n requireNearbyToolData: true,\n menuId: 'measurementsContextMenu',\n },\n },\n ],\n },\n};\n\n/**\n * Generates a name, consisting of:\n * * alt when the alt key is down\n * * ctrl when the cctrl key is down\n * * shift when the shift key is down\n * * 'button' followed by the button number (1 left, 3 right etc)\n */\nfunction getEventName(evt) {\n const button = evt.detail.event.which;\n const nameArr = [];\n if (evt.detail.event.altKey) {\n nameArr.push('alt');\n }\n if (evt.detail.event.ctrlKey) {\n nameArr.push('ctrl');\n }\n if (evt.detail.event.shiftKey) {\n nameArr.push('shift');\n }\n nameArr.push('button');\n nameArr.push(button);\n return nameArr.join('');\n}\n\nfunction initContextMenu({\n cornerstoneViewportService,\n customizationService,\n commandsManager,\n}): void {\n /*\n * Run the commands associated with the given button press,\n * defaults on button1 and button2\n */\n const cornerstoneViewportHandleEvent = (name, evt) => {\n const customizations =\n customizationService.get('cornerstoneViewportClickCommands') || DEFAULT_CONTEXT_MENU_CLICKS;\n const toRun = customizations[name];\n\n if (!toRun) {\n return;\n }\n\n // only find nearbyToolData if required, for the click (which closes the context menu\n // we don't need to find nearbyToolData)\n let nearbyToolData = null;\n if (toRun.commands.some(command => command.commandOptions?.requireNearbyToolData)) {\n nearbyToolData = findNearbyToolData(commandsManager, evt);\n }\n\n const options = {\n nearbyToolData,\n event: evt,\n };\n commandsManager.run(toRun, options);\n };\n\n const cornerstoneViewportHandleClick = evt => {\n const name = getEventName(evt);\n cornerstoneViewportHandleEvent(name, evt);\n };\n\n function elementEnabledHandler(evt) {\n const { viewportId, element } = evt.detail;\n const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);\n if (!viewportInfo) {\n return;\n }\n // TODO check update upstream\n setEnabledElement(viewportId, element);\n\n element.addEventListener(cs3DToolsEvents.MOUSE_CLICK, cornerstoneViewportHandleClick);\n }\n\n function elementDisabledHandler(evt) {\n const { element } = evt.detail;\n\n element.removeEventListener(cs3DToolsEvents.MOUSE_CLICK, cornerstoneViewportHandleClick);\n }\n\n eventTarget.addEventListener(EVENTS.ELEMENT_ENABLED, elementEnabledHandler.bind(null));\n\n eventTarget.addEventListener(EVENTS.ELEMENT_DISABLED, elementDisabledHandler.bind(null));\n}\n\nexport default initContextMenu;\n","import { eventTarget, EVENTS } from '@cornerstonejs/core';\nimport { Enums } from '@cornerstonejs/tools';\nimport { CommandsManager, CustomizationService, Types } from '@ohif/core';\nimport { findNearbyToolData } from './utils/findNearbyToolData';\n\nconst cs3DToolsEvents = Enums.Events;\n\nconst DEFAULT_DOUBLE_CLICK = {\n doubleClick: {\n commandName: 'toggleOneUp',\n commandOptions: {},\n },\n};\n\n/**\n * Generates a double click event name, consisting of:\n * * alt when the alt key is down\n * * ctrl when the cctrl key is down\n * * shift when the shift key is down\n * * 'doubleClick'\n */\nfunction getDoubleClickEventName(evt: CustomEvent) {\n const nameArr = [];\n if (evt.detail.event.altKey) {\n nameArr.push('alt');\n }\n if (evt.detail.event.ctrlKey) {\n nameArr.push('ctrl');\n }\n if (evt.detail.event.shiftKey) {\n nameArr.push('shift');\n }\n nameArr.push('doubleClick');\n return nameArr.join('');\n}\n\nexport type initDoubleClickArgs = {\n customizationService: CustomizationService;\n commandsManager: CommandsManager;\n};\n\nfunction initDoubleClick({ customizationService, commandsManager }: initDoubleClickArgs): void {\n const cornerstoneViewportHandleDoubleClick = (evt: CustomEvent) => {\n // Do not allow double click on a tool.\n const nearbyToolData = findNearbyToolData(commandsManager, evt);\n if (nearbyToolData) {\n return;\n }\n\n const eventName = getDoubleClickEventName(evt);\n\n // Allows for the customization of the double click on a viewport.\n const customizations =\n customizationService.get('cornerstoneViewportClickCommands') || DEFAULT_DOUBLE_CLICK;\n\n const toRun = customizations[eventName];\n\n if (!toRun) {\n return;\n }\n\n commandsManager.run(toRun);\n };\n\n function elementEnabledHandler(evt: CustomEvent) {\n const { element } = evt.detail;\n\n element.addEventListener(\n cs3DToolsEvents.MOUSE_DOUBLE_CLICK,\n cornerstoneViewportHandleDoubleClick\n );\n }\n\n function elementDisabledHandler(evt: CustomEvent) {\n const { element } = evt.detail;\n\n element.removeEventListener(\n cs3DToolsEvents.MOUSE_DOUBLE_CLICK,\n cornerstoneViewportHandleDoubleClick\n );\n }\n\n eventTarget.addEventListener(EVENTS.ELEMENT_ENABLED, elementEnabledHandler.bind(null));\n\n eventTarget.addEventListener(EVENTS.ELEMENT_DISABLED, elementDisabledHandler.bind(null));\n}\n\nexport default initDoubleClick;\n","import { log, Types } from '@ohif/core';\nimport { EVENTS } from '@cornerstonejs/core';\n\nconst { TimingEnum } = Types;\n\nconst IMAGE_TIMING_KEYS = [\n TimingEnum.DISPLAY_SETS_TO_ALL_IMAGES,\n TimingEnum.DISPLAY_SETS_TO_FIRST_IMAGE,\n TimingEnum.STUDY_TO_FIRST_IMAGE,\n];\n\nconst imageTiming = {\n viewportsWaiting: 0,\n};\n\n/**\n * Defines the initial view timing reporting.\n * This allows knowing how many viewports are waiting for initial views and\n * when the IMAGE_RENDERED gets sent out.\n * The first image rendered will fire the FIRST_IMAGE timeEnd logs, while\n * the last of the enabled viewport will fire the ALL_IMAGES timeEnd logs.\n *\n */\n\nexport default function initViewTiming({ element }) {\n if (!IMAGE_TIMING_KEYS.find(key => log.timingKeys[key])) {\n return;\n }\n imageTiming.viewportsWaiting += 1;\n element.addEventListener(EVENTS.IMAGE_RENDERED, imageRenderedListener);\n}\n\nfunction imageRenderedListener(evt) {\n if (evt.detail.viewportStatus === 'preRender') {\n return;\n }\n log.timeEnd(TimingEnum.DISPLAY_SETS_TO_FIRST_IMAGE);\n log.timeEnd(TimingEnum.STUDY_TO_FIRST_IMAGE);\n log.timeEnd(TimingEnum.SCRIPT_TO_VIEW);\n imageTiming.viewportsWaiting -= 1;\n evt.detail.element.removeEventListener(EVENTS.IMAGE_RENDERED, imageRenderedListener);\n if (!imageTiming.viewportsWaiting) {\n log.timeEnd(TimingEnum.DISPLAY_SETS_TO_ALL_IMAGES);\n }\n}\n","import OHIF, { Types } from '@ohif/core';\nimport React from 'react';\n\nimport * as cornerstone from '@cornerstonejs/core';\nimport * as cornerstoneTools from '@cornerstonejs/tools';\nimport {\n init as cs3DInit,\n eventTarget,\n EVENTS,\n metaData,\n volumeLoader,\n imageLoadPoolManager,\n Settings,\n utilities as csUtilities,\n Enums as csEnums,\n} from '@cornerstonejs/core';\nimport { Enums } from '@cornerstonejs/tools';\nimport { cornerstoneStreamingImageVolumeLoader } from '@cornerstonejs/streaming-image-volume-loader';\n\nimport initWADOImageLoader from './initWADOImageLoader';\nimport initCornerstoneTools from './initCornerstoneTools';\n\nimport { connectToolsToMeasurementService } from './initMeasurementService';\nimport initCineService from './initCineService';\nimport interleaveCenterLoader from './utils/interleaveCenterLoader';\nimport nthLoader from './utils/nthLoader';\nimport interleaveTopToBottom from './utils/interleaveTopToBottom';\nimport initContextMenu from './initContextMenu';\nimport initDoubleClick from './initDoubleClick';\nimport { CornerstoneServices } from './types';\nimport initViewTiming from './utils/initViewTiming';\n\n// TODO: Cypress tests are currently grabbing this from the window?\nwindow.cornerstone = cornerstone;\nwindow.cornerstoneTools = cornerstoneTools;\n/**\n *\n */\nexport default async function init({\n servicesManager,\n commandsManager,\n extensionManager,\n configuration,\n appConfig,\n}: Types.Extensions.ExtensionParams): Promise {\n // Note: this should run first before initializing the cornerstone\n // DO NOT CHANGE THE ORDER\n const value = appConfig.useSharedArrayBuffer;\n let sharedArrayBufferDisabled = false;\n\n if (value === 'AUTO') {\n cornerstone.setUseSharedArrayBuffer(csEnums.SharedArrayBufferModes.AUTO);\n } else if (value === 'FALSE' || value === false) {\n cornerstone.setUseSharedArrayBuffer(csEnums.SharedArrayBufferModes.FALSE);\n sharedArrayBufferDisabled = true;\n } else {\n cornerstone.setUseSharedArrayBuffer(csEnums.SharedArrayBufferModes.TRUE);\n }\n\n await cs3DInit({\n rendering: {\n preferSizeOverAccuracy: Boolean(appConfig.use16BitDataType),\n useNorm16Texture: Boolean(appConfig.use16BitDataType),\n },\n });\n\n // For debugging e2e tests that are failing on CI\n cornerstone.setUseCPURendering(Boolean(appConfig.useCPURendering));\n\n cornerstone.setConfiguration({\n ...cornerstone.getConfiguration(),\n rendering: {\n ...cornerstone.getConfiguration().rendering,\n strictZSpacingForVolumeViewport: appConfig.strictZSpacingForVolumeViewport,\n },\n });\n\n // For debugging large datasets, otherwise prefer the defaults\n const { maxCacheSize } = appConfig;\n if (maxCacheSize) {\n cornerstone.cache.setMaxCacheSize(maxCacheSize);\n }\n\n initCornerstoneTools();\n\n Settings.getRuntimeSettings().set('useCursors', Boolean(appConfig.useCursors));\n\n const {\n userAuthenticationService,\n customizationService,\n uiModalService,\n uiNotificationService,\n cineService,\n cornerstoneViewportService,\n hangingProtocolService,\n toolGroupService,\n toolbarService,\n viewportGridService,\n stateSyncService,\n } = servicesManager.services as CornerstoneServices;\n\n window.services = servicesManager.services;\n window.extensionManager = extensionManager;\n window.commandsManager = commandsManager;\n\n if (\n appConfig.showWarningMessageForCrossOrigin &&\n !window.crossOriginIsolated &&\n !sharedArrayBufferDisabled\n ) {\n uiNotificationService.show({\n title: 'Cross Origin Isolation',\n message:\n 'Cross Origin Isolation is not enabled, read more about it here: https://docs.ohif.org/faq/',\n type: 'warning',\n });\n }\n\n if (appConfig.showCPUFallbackMessage && cornerstone.getShouldUseCPURendering()) {\n _showCPURenderingModal(uiModalService, hangingProtocolService);\n }\n\n // Stores a map from `lutPresentationId` to a Presentation object so that\n // an OHIFCornerstoneViewport can be redisplayed with the same LUT\n stateSyncService.register('lutPresentationStore', { clearOnModeExit: true });\n\n // Stores a map from `positionPresentationId` to a Presentation object so that\n // an OHIFCornerstoneViewport can be redisplayed with the same position\n stateSyncService.register('positionPresentationStore', {\n clearOnModeExit: true,\n });\n\n // Stores the entire ViewportGridService getState when toggling to one up\n // (e.g. via a double click) so that it can be restored when toggling back.\n stateSyncService.register('toggleOneUpViewportGridStore', {\n clearOnModeExit: true,\n });\n\n const labelmapRepresentation = cornerstoneTools.Enums.SegmentationRepresentations.Labelmap;\n\n cornerstoneTools.segmentation.config.setGlobalRepresentationConfig(labelmapRepresentation, {\n fillAlpha: 0.3,\n fillAlphaInactive: 0.2,\n outlineOpacity: 1,\n outlineOpacityInactive: 0.65,\n });\n\n const metadataProvider = OHIF.classes.MetadataProvider;\n\n volumeLoader.registerVolumeLoader(\n 'cornerstoneStreamingImageVolume',\n cornerstoneStreamingImageVolumeLoader\n );\n\n hangingProtocolService.registerImageLoadStrategy('interleaveCenter', interleaveCenterLoader);\n hangingProtocolService.registerImageLoadStrategy('interleaveTopToBottom', interleaveTopToBottom);\n hangingProtocolService.registerImageLoadStrategy('nth', nthLoader);\n\n // add metadata providers\n metaData.addProvider(\n csUtilities.calibratedPixelSpacingMetadataProvider.get.bind(\n csUtilities.calibratedPixelSpacingMetadataProvider\n )\n ); // this provider is required for Calibration tool\n metaData.addProvider(metadataProvider.get.bind(metadataProvider), 9999);\n\n imageLoadPoolManager.maxNumRequests = {\n interaction: appConfig?.maxNumRequests?.interaction || 100,\n thumbnail: appConfig?.maxNumRequests?.thumbnail || 75,\n prefetch: appConfig?.maxNumRequests?.prefetch || 10,\n };\n\n initWADOImageLoader(userAuthenticationService, appConfig, extensionManager);\n\n /* Measurement Service */\n this.measurementServiceSource = connectToolsToMeasurementService(servicesManager);\n\n initCineService(cineService);\n\n // When a custom image load is performed, update the relevant viewports\n hangingProtocolService.subscribe(\n hangingProtocolService.EVENTS.CUSTOM_IMAGE_LOAD_PERFORMED,\n volumeInputArrayMap => {\n for (const entry of volumeInputArrayMap.entries()) {\n const [viewportId, volumeInputArray] = entry;\n const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);\n\n const ohifViewport = cornerstoneViewportService.getViewportInfo(viewportId);\n\n const { lutPresentationStore, positionPresentationStore } = stateSyncService.getState();\n const { presentationIds } = ohifViewport.getViewportOptions();\n const presentations = {\n positionPresentation: positionPresentationStore[presentationIds?.positionPresentationId],\n lutPresentation: lutPresentationStore[presentationIds?.lutPresentationId],\n };\n\n cornerstoneViewportService.setVolumesForViewport(viewport, volumeInputArray, presentations);\n }\n }\n );\n\n initContextMenu({\n cornerstoneViewportService,\n customizationService,\n commandsManager,\n });\n\n initDoubleClick({\n customizationService,\n commandsManager,\n });\n\n /**\n * When a viewport gets a new display set, this call will go through all the\n * active tools in the toolbar, and call any commands registered in the\n * toolbar service with a callback to re-enable on displaying the viewport.\n */\n const toolbarEventListener = evt => {\n const { element } = evt.detail;\n const activeTools = toolbarService.getActiveTools();\n\n activeTools.forEach(tool => {\n const toolData = toolbarService.getNestedButton(tool);\n const commands = toolData?.listeners?.[evt.type];\n commandsManager.run(commands, { element, evt });\n });\n };\n\n /** Listens for active viewport events and fires the toolbar listeners */\n const activeViewportEventListener = evt => {\n const { viewportId } = evt;\n const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);\n\n const activeTools = toolbarService.getActiveTools();\n\n activeTools.forEach(tool => {\n if (!toolGroup?._toolInstances?.[tool]) {\n return;\n }\n\n // check if tool is active on the new viewport\n const toolEnabled = toolGroup._toolInstances[tool].mode === Enums.ToolModes.Enabled;\n\n if (!toolEnabled) {\n return;\n }\n\n const button = toolbarService.getNestedButton(tool);\n const commands = button?.listeners?.[evt.type];\n commandsManager.run(commands, { viewportId, evt });\n });\n };\n\n const resetCrosshairs = evt => {\n const { element } = evt.detail;\n const { viewportId, renderingEngineId } = cornerstone.getEnabledElement(element);\n\n const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroupForViewport(\n viewportId,\n renderingEngineId\n );\n\n if (!toolGroup || !toolGroup._toolInstances?.['Crosshairs']) {\n return;\n }\n\n const mode = toolGroup._toolInstances['Crosshairs'].mode;\n\n if (mode === Enums.ToolModes.Active) {\n toolGroup.setToolActive('Crosshairs');\n } else if (mode === Enums.ToolModes.Passive) {\n toolGroup.setToolPassive('Crosshairs');\n } else if (mode === Enums.ToolModes.Enabled) {\n toolGroup.setToolEnabled('Crosshairs');\n }\n };\n\n eventTarget.addEventListener(EVENTS.STACK_VIEWPORT_NEW_STACK, evt => {\n const { element } = evt.detail;\n cornerstoneTools.utilities.stackContextPrefetch.enable(element);\n });\n\n function elementEnabledHandler(evt) {\n const { element } = evt.detail;\n element.addEventListener(EVENTS.CAMERA_RESET, resetCrosshairs);\n\n eventTarget.addEventListener(EVENTS.STACK_VIEWPORT_NEW_STACK, toolbarEventListener);\n\n initViewTiming({ element, eventTarget });\n }\n\n function elementDisabledHandler(evt) {\n const { element } = evt.detail;\n\n element.removeEventListener(EVENTS.CAMERA_RESET, resetCrosshairs);\n\n // TODO - consider removing the callback when all elements are gone\n // eventTarget.removeEventListener(\n // EVENTS.STACK_VIEWPORT_NEW_STACK,\n // newStackCallback\n // );\n }\n\n eventTarget.addEventListener(EVENTS.ELEMENT_ENABLED, elementEnabledHandler.bind(null));\n\n eventTarget.addEventListener(EVENTS.ELEMENT_DISABLED, elementDisabledHandler.bind(null));\n\n viewportGridService.subscribe(\n viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED,\n activeViewportEventListener\n );\n }\n\nfunction CPUModal() {\n return (\n
\n

\n Your computer does not have enough GPU power to support the default GPU rendering mode. OHIF\n has switched to CPU rendering mode. Please note that CPU rendering does not support all\n features such as Volume Rendering, Multiplanar Reconstruction, and Segmentation Overlays.\n

\n
\n );\n}\n\nfunction _showCPURenderingModal(uiModalService, hangingProtocolService) {\n const callback = progress => {\n if (progress === 100) {\n uiModalService.show({\n content: CPUModal,\n title: 'OHIF Fell Back to CPU Rendering',\n });\n\n return true;\n }\n };\n\n const { unsubscribe } = hangingProtocolService.subscribe(\n hangingProtocolService.EVENTS.PROTOCOL_CHANGED,\n () => {\n const done = callback(100);\n\n if (done) {\n unsubscribe();\n }\n }\n );\n}\n","import dicomImageLoader from '@cornerstonejs/dicom-image-loader';\n\nimport { PubSubService } from '@ohif/core';\n\nexport const EVENTS = {\n PROGRESS: 'event:DicomFileUploader:progress',\n};\n\nexport interface DicomFileUploaderEvent {\n fileId: number;\n}\n\nexport interface DicomFileUploaderProgressEvent extends DicomFileUploaderEvent {\n percentComplete: number;\n}\n\nexport enum UploadStatus {\n NotStarted,\n InProgress,\n Success,\n Failed,\n Cancelled,\n}\n\ntype CancelOrFailed = UploadStatus.Cancelled | UploadStatus.Failed;\n\nexport class UploadRejection {\n message: string;\n status: CancelOrFailed;\n\n constructor(status: CancelOrFailed, message: string) {\n this.message = message;\n this.status = status;\n }\n}\n\nexport default class DicomFileUploader extends PubSubService {\n private _file;\n private _fileId;\n private _dataSource;\n private _loadPromise;\n private _abortController = new AbortController();\n private _status: UploadStatus = UploadStatus.NotStarted;\n private _percentComplete = 0;\n\n constructor(file, dataSource) {\n super(EVENTS);\n this._file = file;\n this._fileId = dicomImageLoader.wadouri.fileManager.add(file);\n this._dataSource = dataSource;\n }\n\n getFileId(): string {\n return this._fileId;\n }\n\n getFileName(): string {\n return this._file.name;\n }\n\n getFileSize(): number {\n return this._file.size;\n }\n\n cancel(): void {\n this._abortController.abort();\n }\n\n getStatus(): UploadStatus {\n return this._status;\n }\n\n getPercentComplete(): number {\n return this._percentComplete;\n }\n\n async load(): Promise {\n if (this._loadPromise) {\n // Already started loading, return the load promise.\n return this._loadPromise;\n }\n\n this._loadPromise = new Promise((resolve, reject) => {\n // The upload listeners: fire progress events and/or settle the promise.\n const uploadCallbacks = {\n progress: evt => {\n if (!evt.lengthComputable) {\n // Progress computation is not possible.\n return;\n }\n\n this._status = UploadStatus.InProgress;\n\n this._percentComplete = Math.round((100 * evt.loaded) / evt.total);\n this._broadcastEvent(EVENTS.PROGRESS, {\n fileId: this._fileId,\n percentComplete: this._percentComplete,\n });\n },\n timeout: () => {\n this._reject(reject, new UploadRejection(UploadStatus.Failed, 'The request timed out.'));\n },\n abort: () => {\n this._reject(reject, new UploadRejection(UploadStatus.Cancelled, 'Cancelled'));\n },\n error: () => {\n this._reject(reject, new UploadRejection(UploadStatus.Failed, 'The request failed.'));\n },\n };\n\n // First try to load the file.\n dicomImageLoader.wadouri\n .loadFileRequest(this._fileId)\n .then(dicomFile => {\n if (this._abortController.signal.aborted) {\n this._reject(reject, new UploadRejection(UploadStatus.Cancelled, 'Cancelled'));\n return;\n }\n\n if (!this._checkDicomFile(dicomFile)) {\n // The file is not DICOM\n this._reject(\n reject,\n new UploadRejection(UploadStatus.Failed, 'Not a valid DICOM file.')\n );\n return;\n }\n\n const request = new XMLHttpRequest();\n this._addRequestCallbacks(request, uploadCallbacks);\n\n // Do the actual upload by supplying the DICOM file and upload callbacks/listeners.\n return this._dataSource.store\n .dicom(dicomFile, request)\n .then(() => {\n this._status = UploadStatus.Success;\n resolve();\n })\n .catch(reason => {\n this._reject(reject, reason);\n });\n })\n .catch(reason => {\n this._reject(reject, reason);\n });\n });\n\n return this._loadPromise;\n }\n\n private _isRejected(): boolean {\n return this._status === UploadStatus.Failed || this._status === UploadStatus.Cancelled;\n }\n\n private _reject(reject: (reason?: any) => void, reason: any) {\n if (this._isRejected()) {\n return;\n }\n\n if (reason instanceof UploadRejection) {\n this._status = reason.status;\n reject(reason);\n return;\n }\n\n this._status = UploadStatus.Failed;\n\n if (reason.message) {\n reject(new UploadRejection(UploadStatus.Failed, reason.message));\n return;\n }\n\n reject(new UploadRejection(UploadStatus.Failed, reason));\n }\n\n private _addRequestCallbacks(request: XMLHttpRequest, uploadCallbacks) {\n const abortCallback = () => request.abort();\n this._abortController.signal.addEventListener('abort', abortCallback);\n\n for (const [eventName, callback] of Object.entries(uploadCallbacks)) {\n request.upload.addEventListener(eventName, callback);\n }\n\n const cleanUpCallback = () => {\n this._abortController.signal.removeEventListener('abort', abortCallback);\n\n for (const [eventName, callback] of Object.entries(uploadCallbacks)) {\n request.upload.removeEventListener(eventName, callback);\n }\n\n request.removeEventListener('loadend', cleanUpCallback);\n };\n request.addEventListener('loadend', cleanUpCallback);\n }\n\n private _checkDicomFile(arrayBuffer: ArrayBuffer) {\n if (arrayBuffer.length <= 132) {\n return false;\n }\n const arr = new Uint8Array(arrayBuffer.slice(128, 132));\n // bytes from 128 to 132 must be \"DICM\"\n return Array.from('DICM').every((char, i) => char.charCodeAt(0) === arr[i]);\n }\n}\n","import React, { ReactElement, memo, useCallback, useEffect, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport DicomFileUploader, {\n DicomFileUploaderProgressEvent,\n EVENTS,\n UploadRejection,\n UploadStatus,\n} from '../../utils/DicomFileUploader';\nimport { Icon } from '@ohif/ui';\n\ntype DicomUploadProgressItemProps = {\n dicomFileUploader: DicomFileUploader;\n};\n\n// eslint-disable-next-line react/display-name\nconst DicomUploadProgressItem = memo(\n ({ dicomFileUploader }: DicomUploadProgressItemProps): ReactElement => {\n const [percentComplete, setPercentComplete] = useState(dicomFileUploader.getPercentComplete());\n const [failedReason, setFailedReason] = useState('');\n const [status, setStatus] = useState(dicomFileUploader.getStatus());\n\n const isComplete = useCallback(() => {\n return (\n status === UploadStatus.Failed ||\n status === UploadStatus.Cancelled ||\n status === UploadStatus.Success\n );\n }, [status]);\n\n useEffect(() => {\n const progressSubscription = dicomFileUploader.subscribe(\n EVENTS.PROGRESS,\n (dicomFileUploaderProgressEvent: DicomFileUploaderProgressEvent) => {\n setPercentComplete(dicomFileUploaderProgressEvent.percentComplete);\n }\n );\n\n dicomFileUploader\n .load()\n .catch((reason: UploadRejection) => {\n setStatus(reason.status);\n setFailedReason(reason.message ?? '');\n })\n .finally(() => setStatus(dicomFileUploader.getStatus()));\n\n return () => progressSubscription.unsubscribe();\n }, []);\n\n const cancelUpload = useCallback(() => {\n dicomFileUploader.cancel();\n }, []);\n\n const getStatusIcon = (): ReactElement => {\n switch (dicomFileUploader.getStatus()) {\n case UploadStatus.Success:\n return (\n \n );\n case UploadStatus.InProgress:\n return ;\n case UploadStatus.Failed:\n return ;\n case UploadStatus.Cancelled:\n return ;\n default:\n return <>;\n }\n };\n\n return (\n
\n
\n
\n
{getStatusIcon()}
\n
\n {dicomFileUploader.getFileName()}\n
\n
\n {failedReason &&
{failedReason}
}\n
\n
\n {!isComplete() && (\n <>\n {dicomFileUploader.getStatus() === UploadStatus.InProgress && (\n
{percentComplete}%
\n )}\n
\n \n
\n \n )}\n
\n
\n );\n }\n);\n\nDicomUploadProgressItem.propTypes = {\n dicomFileUploader: PropTypes.instanceOf(DicomFileUploader).isRequired,\n};\n\nexport default DicomUploadProgressItem;\n","import React, { useCallback, useEffect, useRef, useState, ReactElement } from 'react';\nimport PropTypes from 'prop-types';\nimport { Button, Icon, ProgressLoadingBar } from '@ohif/ui';\nimport DicomFileUploader, {\n EVENTS,\n UploadStatus,\n DicomFileUploaderProgressEvent,\n UploadRejection,\n} from '../../utils/DicomFileUploader';\nimport DicomUploadProgressItem from './DicomUploadProgressItem';\nimport classNames from 'classnames';\n\ntype DicomUploadProgressProps = {\n dicomFileUploaderArr: DicomFileUploader[];\n onComplete: () => void;\n};\n\nconst ONE_SECOND = 1000;\nconst ONE_MINUTE = ONE_SECOND * 60;\nconst ONE_HOUR = ONE_MINUTE * 60;\n\n// The base/initial interval time length used to calculate the\n// rate of the upload and in turn estimate the\n// the amount of time remaining for the upload. This is the length\n// of the very first interval to get a reasonable estimate on screen in\n// a reasonable amount of time. The length of each interval after the first\n// is based on the upload rate calculated. Faster rates use this base interval\n// length. Slower rates below UPLOAD_RATE_THRESHOLD get longer interval times\n// to obtain more accurate upload rates.\nconst BASE_INTERVAL_TIME = 15000;\n\n// The upload rate threshold to determine the length of the interval to\n// calculate the upload rate.\nconst UPLOAD_RATE_THRESHOLD = 75;\n\nconst NO_WRAP_ELLIPSIS_CLASS_NAMES = 'text-ellipsis whitespace-nowrap overflow-hidden';\n\nfunction DicomUploadProgress({\n dicomFileUploaderArr,\n onComplete,\n}: DicomUploadProgressProps): ReactElement {\n const [totalUploadSize] = useState(\n dicomFileUploaderArr.reduce((acc, fileUploader) => acc + fileUploader.getFileSize(), 0)\n );\n\n const currentUploadSizeRef = useRef(0);\n\n const uploadRateRef = useRef(0);\n\n const [timeRemaining, setTimeRemaining] = useState(null);\n\n const [percentComplete, setPercentComplete] = useState(0);\n\n const [numFilesCompleted, setNumFilesCompleted] = useState(0);\n\n const [numFails, setNumFails] = useState(0);\n\n const [showFailedOnly, setShowFailedOnly] = useState(false);\n\n const progressBarContainerRef = useRef();\n\n /**\n * The effect for measuring and setting the current upload rate. This is\n * done by measuring the amount of data uploaded in a set interval time.\n */\n useEffect(() => {\n let timeoutId: NodeJS.Timeout;\n\n // The amount of data already uploaded at the start of the interval.\n let intervalStartUploadSize = 0;\n\n // The starting time of the interval.\n let intervalStartTime = Date.now();\n\n const setUploadRateRef = () => {\n const uploadSizeFromStartOfInterval = currentUploadSizeRef.current - intervalStartUploadSize;\n\n const now = Date.now();\n const timeSinceStartOfInterval = now - intervalStartTime;\n\n // Calculate and set the upload rate (ref)\n uploadRateRef.current = uploadSizeFromStartOfInterval / timeSinceStartOfInterval;\n\n // Reset the interval starting values.\n intervalStartUploadSize = currentUploadSizeRef.current;\n intervalStartTime = now;\n\n // Only start a new interval if there is more to upload.\n if (totalUploadSize - currentUploadSizeRef.current > 0) {\n if (uploadRateRef.current >= UPLOAD_RATE_THRESHOLD) {\n timeoutId = setTimeout(setUploadRateRef, BASE_INTERVAL_TIME);\n } else {\n // The current upload rate is relatively slow, so use a larger\n // time interval to get a better upload rate estimate.\n timeoutId = setTimeout(setUploadRateRef, BASE_INTERVAL_TIME * 2);\n }\n }\n };\n\n // The very first interval is just the base time interval length.\n timeoutId = setTimeout(setUploadRateRef, BASE_INTERVAL_TIME);\n\n return () => {\n clearTimeout(timeoutId);\n };\n }, []);\n\n /**\n * The effect for: updating the overall percentage complete; setting the\n * estimated time remaining; updating the number of files uploaded; and\n * detecting if any error has occurred.\n */\n useEffect(() => {\n let currentTimeRemaining = null;\n\n // For each uploader, listen for the progress percentage complete and\n // add promise catch/finally callbacks to detect errors and count number\n // of uploads complete.\n const subscriptions = dicomFileUploaderArr.map(fileUploader => {\n let currentFileUploadSize = 0;\n\n const updateProgress = (percentComplete: number) => {\n const previousFileUploadSize = currentFileUploadSize;\n\n currentFileUploadSize = Math.round((percentComplete / 100) * fileUploader.getFileSize());\n\n currentUploadSizeRef.current = Math.min(\n totalUploadSize,\n currentUploadSizeRef.current - previousFileUploadSize + currentFileUploadSize\n );\n\n setPercentComplete((currentUploadSizeRef.current / totalUploadSize) * 100);\n\n if (uploadRateRef.current !== 0) {\n const uploadSizeRemaining = totalUploadSize - currentUploadSizeRef.current;\n\n const timeRemaining = Math.round(uploadSizeRemaining / uploadRateRef.current);\n\n if (currentTimeRemaining === null) {\n currentTimeRemaining = timeRemaining;\n setTimeRemaining(currentTimeRemaining);\n return;\n }\n\n // Do not show an increase in the time remaining by two seconds or minutes\n // so as to prevent jumping the time remaining up and down constantly\n // due to rounding, inaccuracies in the estimate and slight variations\n // in upload rates over time.\n if (timeRemaining < ONE_MINUTE) {\n const currentSecondsRemaining = Math.ceil(currentTimeRemaining / ONE_SECOND);\n const secondsRemaining = Math.ceil(timeRemaining / ONE_SECOND);\n const delta = secondsRemaining - currentSecondsRemaining;\n if (delta < 0 || delta > 2) {\n currentTimeRemaining = timeRemaining;\n setTimeRemaining(currentTimeRemaining);\n }\n return;\n }\n\n if (timeRemaining < ONE_HOUR) {\n const currentMinutesRemaining = Math.ceil(currentTimeRemaining / ONE_MINUTE);\n const minutesRemaining = Math.ceil(timeRemaining / ONE_MINUTE);\n const delta = minutesRemaining - currentMinutesRemaining;\n if (delta < 0 || delta > 2) {\n currentTimeRemaining = timeRemaining;\n setTimeRemaining(currentTimeRemaining);\n }\n return;\n }\n\n // Hours remaining...\n currentTimeRemaining = timeRemaining;\n setTimeRemaining(currentTimeRemaining);\n }\n };\n\n const progressCallback = (progressEvent: DicomFileUploaderProgressEvent) => {\n updateProgress(progressEvent.percentComplete);\n };\n\n // Use the uploader promise to flag any error and count the number of\n // uploads completed.\n fileUploader\n .load()\n .catch((rejection: UploadRejection) => {\n if (rejection.status === UploadStatus.Failed) {\n setNumFails(numFails => numFails + 1);\n }\n })\n .finally(() => {\n // If any error occurred, the percent complete progress stops firing\n // but this call to updateProgress nicely puts all finished uploads at 100%.\n updateProgress(100);\n setNumFilesCompleted(numCompleted => numCompleted + 1);\n });\n\n return fileUploader.subscribe(EVENTS.PROGRESS, progressCallback);\n });\n return () => {\n subscriptions.forEach(subscription => subscription.unsubscribe());\n };\n }, []);\n\n const cancelAllUploads = useCallback(async () => {\n for (const dicomFileUploader of dicomFileUploaderArr) {\n // Important: we need a non-blocking way to cancel every upload,\n // otherwise the UI will freeze and the user will not be able\n // to interact with the app and progress will not be updated.\n const promise = new Promise((resolve, reject) => {\n setTimeout(() => {\n dicomFileUploader.cancel();\n resolve();\n }, 0);\n });\n }\n }, []);\n\n const getFormattedTimeRemaining = useCallback((): string => {\n if (timeRemaining == null) {\n return '';\n }\n\n if (timeRemaining < ONE_MINUTE) {\n const secondsRemaining = Math.ceil(timeRemaining / ONE_SECOND);\n return `${secondsRemaining} ${secondsRemaining === 1 ? 'second' : 'seconds'}`;\n }\n\n if (timeRemaining < ONE_HOUR) {\n const minutesRemaining = Math.ceil(timeRemaining / ONE_MINUTE);\n return `${minutesRemaining} ${minutesRemaining === 1 ? 'minute' : 'minutes'}`;\n }\n\n const hoursRemaining = Math.ceil(timeRemaining / ONE_HOUR);\n return `${hoursRemaining} ${hoursRemaining === 1 ? 'hour' : 'hours'}`;\n }, [timeRemaining]);\n\n const getPercentCompleteRounded = useCallback(\n () => Math.min(100, Math.round(percentComplete)),\n [percentComplete]\n );\n\n /**\n * Determines if the progress bar should show the infinite animation or not.\n * Show the infinite animation for progress less than 1% AND if less than\n * one pixel of the progress bar would be displayed.\n */\n const showInfiniteProgressBar = useCallback((): boolean => {\n return (\n getPercentCompleteRounded() < 1 &&\n (progressBarContainerRef?.current?.offsetWidth ?? 0) * (percentComplete / 100) < 1\n );\n }, [getPercentCompleteRounded, percentComplete]);\n\n /**\n * Gets the css style for the 'n of m' (files completed) text. The only css attribute\n * of the style is width such that the 'n of m' is always a fixed width and thus\n * as each file completes uploading the text on screen does not constantly shift\n * left and right.\n */\n const getNofMFilesStyle = useCallback(() => {\n // the number of digits accounts for the digits being on each side of the ' of '\n const numDigits = 2 * dicomFileUploaderArr.length.toString().length;\n // the number of digits + 2 spaces and 2 characters for ' of '\n const numChars = numDigits + 4;\n return { width: `${numChars}ch` };\n }, []);\n\n const getNumCompletedAndTimeRemainingComponent = (): ReactElement => {\n return (\n
\n {numFilesCompleted === dicomFileUploaderArr.length ? (\n <>\n {`${dicomFileUploaderArr.length} ${\n dicomFileUploaderArr.length > 1 ? 'files' : 'file'\n } completed.`}\n \n {'Close'}\n \n \n ) : (\n <>\n \n {`${numFilesCompleted} of ${dicomFileUploaderArr.length}`} \n \n {' files completed.'} \n \n {timeRemaining ? `Less than ${getFormattedTimeRemaining()} remaining. ` : ''}\n \n \n Cancel All Uploads\n \n \n )}\n
\n );\n };\n\n const getShowFailedOnlyIconComponent = (): ReactElement => {\n return (\n
\n {numFails > 0 && (\n
setShowFailedOnly(currentShowFailedOnly => !currentShowFailedOnly)}>\n \n
\n )}\n
\n );\n };\n\n const getPercentCompleteComponent = (): ReactElement => {\n return (\n
\n
\n {numFilesCompleted === dicomFileUploaderArr.length ? (\n <>\n
\n {numFails > 0\n ? `Completed with ${numFails} ${numFails > 1 ? 'errors' : 'error'}!`\n : 'Completed!'}\n
\n {getShowFailedOnlyIconComponent()}\n \n ) : (\n <>\n \n \n
\n
\n
{`${getPercentCompleteRounded()}%`}
\n {getShowFailedOnlyIconComponent()}\n
\n \n )}\n
\n \n );\n };\n\n return (\n
\n {getNumCompletedAndTimeRemainingComponent()}\n
\n {getPercentCompleteComponent()}\n
\n {dicomFileUploaderArr\n .filter(\n dicomFileUploader =>\n !showFailedOnly || dicomFileUploader.getStatus() === UploadStatus.Failed\n )\n .map(dicomFileUploader => (\n \n ))}\n
\n
\n
\n );\n}\n\nDicomUploadProgress.propTypes = {\n dicomFileUploaderArr: PropTypes.arrayOf(PropTypes.instanceOf(DicomFileUploader)).isRequired,\n onComplete: PropTypes.func.isRequired,\n};\n\nexport default DicomUploadProgress;\n","import React, { useCallback, useState } from 'react';\nimport { ReactElement } from 'react';\nimport Dropzone from 'react-dropzone';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport DicomFileUploader from '../../utils/DicomFileUploader';\nimport DicomUploadProgress from './DicomUploadProgress';\nimport { Button, ButtonEnums } from '@ohif/ui';\nimport './DicomUpload.css';\n\ntype DicomUploadProps = {\n dataSource;\n onComplete: () => void;\n onStarted: () => void;\n};\n\nfunction DicomUpload({ dataSource, onComplete, onStarted }: DicomUploadProps): ReactElement {\n const baseClassNames = 'min-h-[480px] flex flex-col bg-black select-none';\n const [dicomFileUploaderArr, setDicomFileUploaderArr] = useState([]);\n\n const onDrop = useCallback(async acceptedFiles => {\n onStarted();\n setDicomFileUploaderArr(acceptedFiles.map(file => new DicomFileUploader(file, dataSource)));\n }, []);\n\n const getDropZoneComponent = (): ReactElement => {\n return (\n {\n onDrop(acceptedFiles);\n }}\n noClick\n >\n {({ getRootProps }) => (\n \n
\n \n {({ getRootProps, getInputProps }) => (\n
\n {}}\n >\n {'Add files'}\n \n \n
\n )}\n \n \n {({ getRootProps, getInputProps }) => (\n
\n {}}\n >\n {'Add folder'}\n \n \n
\n )}\n \n
\n
or drag images or folders here
\n
(DICOM files supported)
\n \n )}\n \n );\n };\n\n return (\n <>\n {dicomFileUploaderArr.length ? (\n
\n \n
\n ) : (\n
{getDropZoneComponent()}
\n )}\n \n );\n}\n\nDicomUpload.propTypes = {\n dataSource: PropTypes.object.isRequired,\n onComplete: PropTypes.func.isRequired,\n onStarted: PropTypes.func.isRequired,\n};\n\nexport default DicomUpload;\n","import { Enums } from '@cornerstonejs/tools';\nimport { toolNames } from './initCornerstoneTools';\nimport DicomUpload from './components/DicomUpload/DicomUpload';\n\nconst tools = {\n active: [\n {\n toolName: toolNames.WindowLevel,\n bindings: [{ mouseButton: Enums.MouseBindings.Primary }],\n },\n {\n toolName: toolNames.Pan,\n bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }],\n },\n {\n toolName: toolNames.Zoom,\n bindings: [{ mouseButton: Enums.MouseBindings.Secondary }],\n },\n { toolName: toolNames.StackScrollMouseWheel, bindings: [] },\n ],\n enabled: [{ toolName: toolNames.SegmentationDisplay }],\n};\n\nfunction getCustomizationModule() {\n return [\n {\n name: 'cornerstoneDicomUploadComponent',\n value: {\n id: 'dicomUploadComponent',\n component: DicomUpload,\n },\n },\n {\n name: 'default',\n value: [\n {\n id: 'cornerstone.overlayViewportTools',\n tools,\n },\n ],\n },\n ];\n}\n\nexport default getCustomizationModule;\n","import React, { useEffect, useState } from 'react';\nimport html2canvas from 'html2canvas';\nimport {\n Enums,\n getEnabledElement,\n getOrCreateCanvas,\n StackViewport,\n VolumeViewport,\n} from '@cornerstonejs/core';\nimport { ToolGroupManager } from '@cornerstonejs/tools';\nimport PropTypes from 'prop-types';\nimport { ViewportDownloadForm } from '@ohif/ui';\n\nimport { getEnabledElement as OHIFgetEnabledElement } from '../state';\n\nconst MINIMUM_SIZE = 100;\nconst DEFAULT_SIZE = 512;\nconst MAX_TEXTURE_SIZE = 10000;\nconst VIEWPORT_ID = 'cornerstone-viewport-download-form';\n\nconst CornerstoneViewportDownloadForm = ({\n onClose,\n activeViewportId: activeViewportIdProp,\n cornerstoneViewportService,\n}) => {\n const enabledElement = OHIFgetEnabledElement(activeViewportIdProp);\n const activeViewportElement = enabledElement?.element;\n const activeViewportEnabledElement = getEnabledElement(activeViewportElement);\n\n const { viewportId: activeViewportId, renderingEngineId } = activeViewportEnabledElement;\n\n const toolGroup = ToolGroupManager.getToolGroupForViewport(activeViewportId, renderingEngineId);\n\n const toolModeAndBindings = Object.keys(toolGroup.toolOptions).reduce((acc, toolName) => {\n const tool = toolGroup.toolOptions[toolName];\n const { mode, bindings } = tool;\n\n return {\n ...acc,\n [toolName]: {\n mode,\n bindings,\n },\n };\n }, {});\n\n useEffect(() => {\n return () => {\n Object.keys(toolModeAndBindings).forEach(toolName => {\n const { mode, bindings } = toolModeAndBindings[toolName];\n toolGroup.setToolMode(toolName, mode, { bindings });\n });\n };\n }, []);\n\n const enableViewport = viewportElement => {\n if (viewportElement) {\n const { renderingEngine, viewport } = getEnabledElement(activeViewportElement);\n\n const viewportInput = {\n viewportId: VIEWPORT_ID,\n element: viewportElement,\n type: viewport.type,\n defaultOptions: {\n background: viewport.defaultOptions.background,\n orientation: viewport.defaultOptions.orientation,\n },\n };\n\n renderingEngine.enableElement(viewportInput);\n }\n };\n\n const disableViewport = viewportElement => {\n if (viewportElement) {\n const { renderingEngine } = getEnabledElement(viewportElement);\n return new Promise(resolve => {\n renderingEngine.disableElement(VIEWPORT_ID);\n });\n }\n };\n\n const updateViewportPreview = (downloadViewportElement, internalCanvas, fileType) =>\n new Promise(resolve => {\n const enabledElement = getEnabledElement(downloadViewportElement);\n\n const { viewport: downloadViewport, renderingEngine } = enabledElement;\n\n // Note: Since any trigger of dimensions will update the viewport,\n // we need to resize the offScreenCanvas to accommodate for the new\n // dimensions, this is due to the reason that we are using the GPU offScreenCanvas\n // to render the viewport for the downloadViewport.\n renderingEngine.resize();\n\n // Trigger the render on the viewport to update the on screen\n downloadViewport.render();\n\n downloadViewportElement.addEventListener(\n Enums.Events.IMAGE_RENDERED,\n function updateViewport(event) {\n const enabledElement = getEnabledElement(event.target);\n const { viewport } = enabledElement;\n const { element } = viewport;\n\n const downloadCanvas = getOrCreateCanvas(element);\n\n const type = 'image/' + fileType;\n const dataUrl = downloadCanvas.toDataURL(type, 1);\n\n let newWidth = element.offsetHeight;\n let newHeight = element.offsetWidth;\n\n if (newWidth > DEFAULT_SIZE || newHeight > DEFAULT_SIZE) {\n const multiplier = DEFAULT_SIZE / Math.max(newWidth, newHeight);\n newHeight *= multiplier;\n newWidth *= multiplier;\n }\n\n resolve({ dataUrl, width: newWidth, height: newHeight });\n\n downloadViewportElement.removeEventListener(Enums.Events.IMAGE_RENDERED, updateViewport);\n }\n );\n });\n\n const loadImage = (activeViewportElement, viewportElement, width, height) =>\n new Promise(resolve => {\n if (activeViewportElement && viewportElement) {\n const activeViewportEnabledElement = getEnabledElement(activeViewportElement);\n\n if (!activeViewportEnabledElement) {\n return;\n }\n\n const { viewport } = activeViewportEnabledElement;\n\n const renderingEngine = cornerstoneViewportService.getRenderingEngine();\n const downloadViewport = renderingEngine.getViewport(VIEWPORT_ID);\n\n if (downloadViewport instanceof StackViewport) {\n const imageId = viewport.getCurrentImageId();\n const properties = viewport.getProperties();\n\n downloadViewport.setStack([imageId]).then(() => {\n try {\n downloadViewport.setProperties(properties);\n const newWidth = Math.min(width || image.width, MAX_TEXTURE_SIZE);\n const newHeight = Math.min(height || image.height, MAX_TEXTURE_SIZE);\n\n resolve({ width: newWidth, height: newHeight });\n } catch (e) {\n // Happens on clicking the cancel button\n console.warn('Unable to set properties', e);\n }\n });\n } else if (downloadViewport instanceof VolumeViewport) {\n const actors = viewport.getActors();\n // downloadViewport.setActors(actors);\n actors.forEach(actor => {\n downloadViewport.addActor(actor);\n });\n\n downloadViewport.setCamera(viewport.getCamera());\n downloadViewport.render();\n\n const newWidth = Math.min(width || image.width, MAX_TEXTURE_SIZE);\n const newHeight = Math.min(height || image.height, MAX_TEXTURE_SIZE);\n\n resolve({ width: newWidth, height: newHeight });\n }\n }\n });\n\n const toggleAnnotations = (toggle, viewportElement, activeViewportElement) => {\n const activeViewportEnabledElement = getEnabledElement(activeViewportElement);\n\n const downloadViewportElement = getEnabledElement(viewportElement);\n\n const { viewportId: activeViewportId, renderingEngineId } = activeViewportEnabledElement;\n const { viewportId: downloadViewportId } = downloadViewportElement;\n\n if (!activeViewportEnabledElement || !downloadViewportElement) {\n return;\n }\n\n const toolGroup = ToolGroupManager.getToolGroupForViewport(activeViewportId, renderingEngineId);\n\n // add the viewport to the toolGroup\n toolGroup.addViewport(downloadViewportId, renderingEngineId);\n\n Object.keys(toolGroup._toolInstances).forEach(toolName => {\n // make all tools Enabled so that they can not be interacted with\n // in the download viewport\n if (toggle && toolName !== 'Crosshairs') {\n try {\n toolGroup.setToolEnabled(toolName);\n } catch (e) {\n console.log(e);\n }\n } else {\n toolGroup.setToolDisabled(toolName);\n }\n });\n };\n\n const downloadBlob = (filename, fileType) => {\n const file = `${filename}.${fileType}`;\n const divForDownloadViewport = document.querySelector(\n `div[data-viewport-uid=\"${VIEWPORT_ID}\"]`\n );\n\n html2canvas(divForDownloadViewport).then(canvas => {\n const link = document.createElement('a');\n link.download = file;\n link.href = canvas.toDataURL(fileType, 1.0);\n link.click();\n });\n };\n\n return (\n \n );\n};\n\nCornerstoneViewportDownloadForm.propTypes = {\n onClose: PropTypes.func,\n activeViewportId: PropTypes.string.isRequired,\n};\n\nexport default CornerstoneViewportDownloadForm;\n","const STACK_SYNC_NAME = 'stackImageSync';\n\nexport default function toggleStackImageSync({\n toggledState,\n servicesManager,\n viewports: providedViewports,\n}) {\n if (!toggledState) {\n return disableSync(STACK_SYNC_NAME, servicesManager);\n }\n\n const { syncGroupService, viewportGridService, displaySetService, cornerstoneViewportService } =\n servicesManager.services;\n\n const viewports =\n providedViewports || getReconstructableStackViewports(viewportGridService, displaySetService);\n\n // create synchronization group and add the viewports to it.\n viewports.forEach(gridViewport => {\n const { viewportId } = gridViewport.viewportOptions;\n const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);\n if (!viewport) {\n return;\n }\n syncGroupService.addViewportToSyncGroup(viewportId, viewport.getRenderingEngine().id, {\n type: 'stackimage',\n id: STACK_SYNC_NAME,\n source: true,\n target: true,\n });\n });\n}\n\nfunction disableSync(syncName, servicesManager) {\n const { syncGroupService, viewportGridService, displaySetService, cornerstoneViewportService } =\n servicesManager.services;\n const viewports = getReconstructableStackViewports(viewportGridService, displaySetService);\n viewports.forEach(gridViewport => {\n const { viewportId } = gridViewport.viewportOptions;\n const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);\n if (!viewport) {\n return;\n }\n syncGroupService.removeViewportFromSyncGroup(\n viewport.id,\n viewport.getRenderingEngine().id,\n syncName\n );\n });\n}\n\n/**\n * Gets the consistent spacing stack viewport types, which are the ones which\n * can be navigated using the stack image sync right now.\n */\nfunction getReconstructableStackViewports(viewportGridService, displaySetService) {\n let { viewports } = viewportGridService.getState();\n\n viewports = [...viewports.values()];\n // filter empty viewports\n viewports = viewports.filter(\n viewport => viewport.displaySetInstanceUIDs && viewport.displaySetInstanceUIDs.length\n );\n\n // filter reconstructable viewports\n viewports = viewports.filter(viewport => {\n const { displaySetInstanceUIDs } = viewport;\n\n for (const displaySetInstanceUID of displaySetInstanceUIDs) {\n const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);\n\n // TODO - add a better test than isReconstructable\n if (displaySet && displaySet.isReconstructable) {\n return true;\n }\n\n return false;\n }\n });\n return viewports;\n}\n","import {\n getEnabledElement,\n StackViewport,\n VolumeViewport,\n utilities as csUtils,\n} from '@cornerstonejs/core';\nimport {\n ToolGroupManager,\n Enums,\n utilities as cstUtils,\n ReferenceLinesTool,\n} from '@cornerstonejs/tools';\nimport { Types as OhifTypes } from '@ohif/core';\n\nimport CornerstoneViewportDownloadForm from './utils/CornerstoneViewportDownloadForm';\nimport callInputDialog from './utils/callInputDialog';\nimport toggleStackImageSync from './utils/stackSync/toggleStackImageSync';\nimport { getFirstAnnotationSelected } from './utils/measurementServiceMappings/utils/selection';\nimport getActiveViewportEnabledElement from './utils/getActiveViewportEnabledElement';\nimport { CornerstoneServices } from './types';\n\nfunction commandsModule({\n servicesManager,\n commandsManager,\n}: OhifTypes.Extensions.ExtensionParams): OhifTypes.Extensions.CommandsModule {\n const {\n viewportGridService,\n toolGroupService,\n cineService,\n toolbarService,\n uiDialogService,\n cornerstoneViewportService,\n uiNotificationService,\n measurementService,\n } = servicesManager.services as CornerstoneServices;\n\n const { measurementServiceSource } = this;\n\n function _getActiveViewportEnabledElement() {\n return getActiveViewportEnabledElement(viewportGridService);\n }\n const actions = {\n /**\n * Generates the selector props for the context menu, specific to\n * the cornerstone viewport, and then runs the context menu.\n */\n showCornerstoneContextMenu: options => {\n const element = _getActiveViewportEnabledElement()?.viewport?.element;\n\n const optionsToUse = { ...options, element };\n const { useSelectedAnnotation, nearbyToolData, event } = optionsToUse;\n\n // This code is used to invoke the context menu via keyboard shortcuts\n if (useSelectedAnnotation && !nearbyToolData) {\n const firstAnnotationSelected = getFirstAnnotationSelected(element);\n // filter by allowed selected tools from config property (if there is any)\n const isToolAllowed =\n !optionsToUse.allowedSelectedTools ||\n optionsToUse.allowedSelectedTools.includes(firstAnnotationSelected?.metadata?.toolName);\n if (isToolAllowed) {\n optionsToUse.nearbyToolData = firstAnnotationSelected;\n } else {\n return;\n }\n }\n\n optionsToUse.defaultPointsPosition = [];\n // if (optionsToUse.nearbyToolData) {\n // optionsToUse.defaultPointsPosition = commandsManager.runCommand(\n // 'getToolDataActiveCanvasPoints',\n // { toolData: optionsToUse.nearbyToolData }\n // );\n // }\n\n // TODO - make the selectorProps richer by including the study metadata and display set.\n optionsToUse.selectorProps = {\n toolName: optionsToUse.nearbyToolData?.metadata?.toolName,\n value: optionsToUse.nearbyToolData,\n uid: optionsToUse.nearbyToolData?.annotationUID,\n nearbyToolData: optionsToUse.nearbyToolData,\n event,\n ...optionsToUse.selectorProps,\n };\n\n commandsManager.run(options, optionsToUse);\n },\n\n getNearbyToolData({ nearbyToolData, element, canvasCoordinates }) {\n return nearbyToolData ?? cstUtils.getAnnotationNearPoint(element, canvasCoordinates);\n },\n getNearbyAnnotation({ element, canvasCoordinates }) {\n const nearbyToolData = actions.getNearbyToolData({\n nearbyToolData: null,\n element,\n canvasCoordinates,\n });\n\n const isAnnotation = toolName => {\n const enabledElement = getEnabledElement(element);\n\n if (!enabledElement) {\n return;\n }\n\n const { renderingEngineId, viewportId } = enabledElement;\n const toolGroup = ToolGroupManager.getToolGroupForViewport(viewportId, renderingEngineId);\n\n const toolInstance = toolGroup.getToolInstance(toolName);\n\n return toolInstance?.constructor?.isAnnotation ?? true;\n };\n\n return nearbyToolData?.metadata?.toolName && isAnnotation(nearbyToolData.metadata.toolName)\n ? nearbyToolData\n : null;\n },\n\n // Measurement tool commands:\n\n /** Delete the given measurement */\n deleteMeasurement: ({ uid }) => {\n if (uid) {\n measurementServiceSource.remove(uid);\n }\n },\n\n /**\n * Show the measurement labelling input dialog and update the label\n * on the measurement with a response if not cancelled.\n */\n setMeasurementLabel: ({ uid }) => {\n const measurement = measurementService.getMeasurement(uid);\n\n callInputDialog(\n uiDialogService,\n measurement,\n (label, actionId) => {\n if (actionId === 'cancel') {\n return;\n }\n\n const updatedMeasurement = Object.assign({}, measurement, {\n label,\n });\n\n measurementService.update(updatedMeasurement.uid, updatedMeasurement, true);\n },\n false\n );\n },\n\n /**\n *\n * @param props - containing the updates to apply\n * @param props.measurementKey - chooses the measurement key to apply the\n * code to. This will typically be finding or site to apply a\n * finding code or a findingSites code.\n * @param props.code - A coding scheme value from DICOM, including:\n * * CodeValue - the language independent code, for example '1234'\n * * CodingSchemeDesignator - the issue of the code value\n * * CodeMeaning - the text value shown to the user\n * * ref - a string reference in the form `:`\n * * Other fields\n * Note it is a valid option to remove the finding or site values by\n * supplying null for the code.\n * @param props.uid - the measurement UID to find it with\n * @param props.label - the text value for the code. Has NOTHING to do with\n * the measurement label, which can be set with textLabel\n * @param props.textLabel is the measurement label to apply. Set to null to\n * delete.\n *\n * If the measurementKey is `site`, then the code will also be added/replace\n * the 0 element of findingSites. This behaviour is expected to be enhanced\n * in the future with ability to set other site information.\n */\n updateMeasurement: props => {\n const { code, uid, textLabel, label } = props;\n const measurement = measurementService.getMeasurement(uid);\n const updatedMeasurement = {\n ...measurement,\n };\n // Call it textLabel as the label value\n // TODO - remove the label setting when direct rendering of findingSites is enabled\n if (textLabel !== undefined) {\n updatedMeasurement.label = textLabel;\n }\n if (code !== undefined) {\n const measurementKey = code.type || 'finding';\n\n if (code.ref && !code.CodeValue) {\n const split = code.ref.indexOf(':');\n code.CodeValue = code.ref.substring(split + 1);\n code.CodeMeaning = code.text || label;\n code.CodingSchemeDesignator = code.ref.substring(0, split);\n }\n updatedMeasurement[measurementKey] = code;\n // TODO - remove this line once the measurements table customizations are in\n if (measurementKey !== 'finding') {\n if (updatedMeasurement.findingSites) {\n updatedMeasurement.findingSites = updatedMeasurement.findingSites.filter(\n it => it.type !== measurementKey\n );\n updatedMeasurement.findingSites.push(code);\n } else {\n updatedMeasurement.findingSites = [code];\n }\n }\n }\n measurementService.update(updatedMeasurement.uid, updatedMeasurement, true);\n },\n\n // Retrieve value commands\n getActiveViewportEnabledElement: _getActiveViewportEnabledElement,\n\n setViewportActive: ({ viewportId }) => {\n const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);\n if (!viewportInfo) {\n console.warn('No viewport found for viewportId:', viewportId);\n return;\n }\n\n viewportGridService.setActiveViewportId(viewportId);\n },\n arrowTextCallback: ({ callback, data }) => {\n callInputDialog(uiDialogService, data, callback);\n },\n cleanUpCrosshairs: () => {\n // if the crosshairs tool is active, deactivate it and set window level active\n // since we are going back to main non-mpr HP\n const activeViewportToolGroup = toolGroupService.getToolGroup(null);\n\n if (activeViewportToolGroup._toolInstances?.Crosshairs?.mode === Enums.ToolModes.Active) {\n actions.toolbarServiceRecordInteraction({\n interactionType: 'tool',\n commands: [\n {\n commandOptions: {\n toolName: 'WindowLevel',\n },\n context: 'CORNERSTONE',\n },\n ],\n });\n }\n },\n toggleCine: () => {\n const { viewports } = viewportGridService.getState();\n const { isCineEnabled } = cineService.getState();\n cineService.setIsCineEnabled(!isCineEnabled);\n toolbarService.setButton('Cine', { props: { isActive: !isCineEnabled } });\n viewports.forEach((_, index) => cineService.setCine({ id: index, isPlaying: false }));\n },\n setWindowLevel({ window, level, toolGroupId }) {\n // convert to numbers\n const windowWidthNum = Number(window);\n const windowCenterNum = Number(level);\n\n const { viewportId } = _getActiveViewportEnabledElement();\n const viewportToolGroupId = toolGroupService.getToolGroupForViewport(viewportId);\n\n if (toolGroupId && toolGroupId !== viewportToolGroupId) {\n return;\n }\n\n // get actor from the viewport\n const renderingEngine = cornerstoneViewportService.getRenderingEngine();\n const viewport = renderingEngine.getViewport(viewportId);\n\n const { lower, upper } = csUtils.windowLevel.toLowHighRange(windowWidthNum, windowCenterNum);\n\n viewport.setProperties({\n voiRange: {\n upper,\n lower,\n },\n });\n viewport.render();\n },\n\n // Just call the toolbar service record interaction - allows\n // executing a toolbar command as a full toolbar command with side affects\n // coming from the ToolbarService itself.\n toolbarServiceRecordInteraction: props => {\n toolbarService.recordInteraction(props);\n },\n // Enable or disable a toggleable command, without calling the activation\n // Used to setup already active tools from hanging protocols\n setToolbarToggled: props => {\n toolbarService.setToggled(props.toolId, props.isActive ?? true);\n },\n setToolActive: ({ toolName, toolGroupId = null, toggledState }) => {\n if (toolName === 'Crosshairs') {\n const activeViewportToolGroup = toolGroupService.getToolGroup(null);\n\n if (!activeViewportToolGroup._toolInstances.Crosshairs) {\n uiNotificationService.show({\n title: 'Crosshairs',\n message:\n 'You need to be in a MPR view to use Crosshairs. Click on MPR button in the toolbar to activate it.',\n type: 'info',\n duration: 3000,\n });\n\n throw new Error('Crosshairs tool is not available in this viewport');\n }\n }\n\n const { viewports } = viewportGridService.getState();\n\n if (!viewports.size) {\n return;\n }\n\n const toolGroup = toolGroupService.getToolGroup(toolGroupId);\n\n if (!toolGroup) {\n return;\n }\n\n if (!toolGroup.getToolInstance(toolName)) {\n uiNotificationService.show({\n title: `${toolName} tool`,\n message: `The ${toolName} tool is not available in this viewport.`,\n type: 'info',\n duration: 3000,\n });\n\n throw new Error(`ToolGroup ${toolGroup.id} does not have this tool.`);\n }\n\n const activeToolName = toolGroup.getActivePrimaryMouseButtonTool();\n\n if (activeToolName) {\n // Todo: this is a hack to prevent the crosshairs to stick around\n // after another tool is selected. We should find a better way to do this\n if (activeToolName === 'Crosshairs') {\n toolGroup.setToolDisabled(activeToolName);\n } else {\n toolGroup.setToolPassive(activeToolName);\n }\n }\n\n // If there is a toggle state, then simply set the enabled/disabled state without\n // setting the tool active.\n if (toggledState != null) {\n toggledState ? toolGroup.setToolEnabled(toolName) : toolGroup.setToolDisabled(toolName);\n return;\n }\n\n // Set the new toolName to be active\n toolGroup.setToolActive(toolName, {\n bindings: [\n {\n mouseButton: Enums.MouseBindings.Primary,\n },\n ],\n });\n },\n showDownloadViewportModal: () => {\n const { activeViewportId } = viewportGridService.getState();\n\n if (!cornerstoneViewportService.getCornerstoneViewport(activeViewportId)) {\n // Cannot download a non-cornerstone viewport (image).\n uiNotificationService.show({\n title: 'Download Image',\n message: 'Image cannot be downloaded',\n type: 'error',\n });\n return;\n }\n\n const { uiModalService } = servicesManager.services;\n\n if (uiModalService) {\n uiModalService.show({\n content: CornerstoneViewportDownloadForm,\n title: 'Download High Quality Image',\n contentProps: {\n activeViewportId,\n onClose: uiModalService.hide,\n cornerstoneViewportService,\n },\n });\n }\n },\n rotateViewport: ({ rotation }) => {\n const enabledElement = _getActiveViewportEnabledElement();\n if (!enabledElement) {\n return;\n }\n\n const { viewport } = enabledElement;\n\n if (viewport instanceof StackViewport) {\n const { rotation: currentRotation } = viewport.getProperties();\n const newRotation = (currentRotation + rotation) % 360;\n viewport.setProperties({ rotation: newRotation });\n viewport.render();\n }\n },\n flipViewportHorizontal: () => {\n const enabledElement = _getActiveViewportEnabledElement();\n\n if (!enabledElement) {\n return;\n }\n\n const { viewport } = enabledElement;\n\n if (viewport instanceof StackViewport) {\n const { flipHorizontal } = viewport.getCamera();\n viewport.setCamera({ flipHorizontal: !flipHorizontal });\n viewport.render();\n }\n },\n flipViewportVertical: () => {\n const enabledElement = _getActiveViewportEnabledElement();\n\n if (!enabledElement) {\n return;\n }\n\n const { viewport } = enabledElement;\n\n if (viewport instanceof StackViewport) {\n const { flipVertical } = viewport.getCamera();\n viewport.setCamera({ flipVertical: !flipVertical });\n viewport.render();\n }\n },\n invertViewport: ({ element }) => {\n let enabledElement;\n\n if (element === undefined) {\n enabledElement = _getActiveViewportEnabledElement();\n } else {\n enabledElement = element;\n }\n\n if (!enabledElement) {\n return;\n }\n\n const { viewport } = enabledElement;\n\n const { invert } = viewport.getProperties();\n viewport.setProperties({ invert: !invert });\n viewport.render();\n },\n resetViewport: () => {\n const enabledElement = _getActiveViewportEnabledElement();\n\n if (!enabledElement) {\n return;\n }\n\n const { viewport } = enabledElement;\n\n if (viewport instanceof StackViewport) {\n viewport.resetProperties();\n viewport.resetCamera();\n } else {\n viewport.resetProperties();\n viewport.resetCamera();\n }\n\n viewport.render();\n },\n scaleViewport: ({ direction }) => {\n const enabledElement = _getActiveViewportEnabledElement();\n const scaleFactor = direction > 0 ? 0.9 : 1.1;\n\n if (!enabledElement) {\n return;\n }\n const { viewport } = enabledElement;\n\n if (viewport instanceof StackViewport) {\n if (direction) {\n const { parallelScale } = viewport.getCamera();\n viewport.setCamera({ parallelScale: parallelScale * scaleFactor });\n viewport.render();\n } else {\n viewport.resetCamera();\n viewport.render();\n }\n }\n },\n\n /** Jumps the active viewport or the specified one to the given slice index */\n jumpToImage: ({ imageIndex, viewport: gridViewport }): void => {\n // Get current active viewport (return if none active)\n let viewport;\n if (!gridViewport) {\n const enabledElement = _getActiveViewportEnabledElement();\n if (!enabledElement) {\n return;\n }\n viewport = enabledElement.viewport;\n } else {\n viewport = cornerstoneViewportService.getCornerstoneViewport(gridViewport.id);\n }\n\n // Get number of slices\n // -> Copied from cornerstone3D jumpToSlice\\_getImageSliceData()\n let numberOfSlices = 0;\n\n if (viewport instanceof StackViewport) {\n numberOfSlices = viewport.getImageIds().length;\n } else if (viewport instanceof VolumeViewport) {\n numberOfSlices = csUtils.getImageSliceDataForVolumeViewport(viewport).numberOfSlices;\n } else {\n throw new Error('Unsupported viewport type');\n }\n\n const jumpIndex = imageIndex < 0 ? numberOfSlices + imageIndex : imageIndex;\n if (jumpIndex >= numberOfSlices || jumpIndex < 0) {\n throw new Error(`Can't jump to ${imageIndex}`);\n }\n\n // Set slice to last slice\n const options = { imageIndex: jumpIndex };\n cstUtils.jumpToSlice(viewport.element, options);\n },\n scroll: ({ direction }) => {\n const enabledElement = _getActiveViewportEnabledElement();\n\n if (!enabledElement) {\n return;\n }\n\n const { viewport } = enabledElement;\n const options = { delta: direction };\n\n cstUtils.scroll(viewport, options);\n },\n setViewportColormap: ({ viewportId, displaySetInstanceUID, colormap, immediate = false }) => {\n const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);\n\n const actorEntries = viewport.getActors();\n\n const actorEntry = actorEntries.find(actorEntry => {\n return actorEntry.uid.includes(displaySetInstanceUID);\n });\n\n const { actor: volumeActor, uid: volumeId } = actorEntry;\n\n viewport.setProperties({ colormap, volumeActor }, volumeId);\n\n if (immediate) {\n viewport.render();\n }\n },\n changeActiveViewport: ({ direction = 1 }) => {\n const { activeViewportId, viewports } = viewportGridService.getState();\n const viewportIds = Array.from(viewports.keys());\n const currentIndex = viewportIds.indexOf(activeViewportId);\n const nextViewportIndex =\n (currentIndex + direction + viewportIds.length) % viewportIds.length;\n viewportGridService.setActiveViewportId(viewportIds[nextViewportIndex] as string);\n },\n\n toggleStackImageSync: ({ toggledState }) => {\n toggleStackImageSync({\n servicesManager,\n toggledState,\n });\n },\n setSourceViewportForReferenceLinesTool: ({ toggledState, viewportId }) => {\n if (!viewportId) {\n const { activeViewportId } = viewportGridService.getState();\n viewportId = activeViewportId;\n }\n\n const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);\n\n toolGroup.setToolConfiguration(\n ReferenceLinesTool.toolName,\n {\n sourceViewportId: viewportId,\n },\n true // overwrite\n );\n },\n storePresentation: ({ viewportId }) => {\n cornerstoneViewportService.storePresentation({ viewportId });\n },\n };\n\n const definitions = {\n // The command here is to show the viewer context menu, as being the\n // context menu\n showCornerstoneContextMenu: {\n commandFn: actions.showCornerstoneContextMenu,\n storeContexts: [],\n options: {\n menuCustomizationId: 'measurementsContextMenu',\n commands: [\n {\n commandName: 'showContextMenu',\n },\n ],\n },\n },\n\n getNearbyToolData: {\n commandFn: actions.getNearbyToolData,\n },\n getNearbyAnnotation: {\n commandFn: actions.getNearbyAnnotation,\n storeContexts: [],\n options: {},\n },\n\n deleteMeasurement: {\n commandFn: actions.deleteMeasurement,\n },\n setMeasurementLabel: {\n commandFn: actions.setMeasurementLabel,\n },\n updateMeasurement: {\n commandFn: actions.updateMeasurement,\n },\n\n setWindowLevel: {\n commandFn: actions.setWindowLevel,\n },\n toolbarServiceRecordInteraction: {\n commandFn: actions.toolbarServiceRecordInteraction,\n },\n setToolActive: {\n commandFn: actions.setToolActive,\n },\n rotateViewportCW: {\n commandFn: actions.rotateViewport,\n options: { rotation: 90 },\n },\n rotateViewportCCW: {\n commandFn: actions.rotateViewport,\n options: { rotation: -90 },\n },\n incrementActiveViewport: {\n commandFn: actions.changeActiveViewport,\n },\n decrementActiveViewport: {\n commandFn: actions.changeActiveViewport,\n options: { direction: -1 },\n },\n flipViewportHorizontal: {\n commandFn: actions.flipViewportHorizontal,\n },\n flipViewportVertical: {\n commandFn: actions.flipViewportVertical,\n },\n invertViewport: {\n commandFn: actions.invertViewport,\n },\n resetViewport: {\n commandFn: actions.resetViewport,\n },\n scaleUpViewport: {\n commandFn: actions.scaleViewport,\n options: { direction: 1 },\n },\n scaleDownViewport: {\n commandFn: actions.scaleViewport,\n options: { direction: -1 },\n },\n fitViewportToWindow: {\n commandFn: actions.scaleViewport,\n options: { direction: 0 },\n },\n nextImage: {\n commandFn: actions.scroll,\n options: { direction: 1 },\n },\n previousImage: {\n commandFn: actions.scroll,\n options: { direction: -1 },\n },\n firstImage: {\n commandFn: actions.jumpToImage,\n options: { imageIndex: 0 },\n },\n lastImage: {\n commandFn: actions.jumpToImage,\n options: { imageIndex: -1 },\n },\n jumpToImage: {\n commandFn: actions.jumpToImage,\n },\n showDownloadViewportModal: {\n commandFn: actions.showDownloadViewportModal,\n },\n toggleCine: {\n commandFn: actions.toggleCine,\n },\n arrowTextCallback: {\n commandFn: actions.arrowTextCallback,\n },\n setViewportActive: {\n commandFn: actions.setViewportActive,\n },\n setViewportColormap: {\n commandFn: actions.setViewportColormap,\n },\n toggleStackImageSync: {\n commandFn: actions.toggleStackImageSync,\n },\n setSourceViewportForReferenceLinesTool: {\n commandFn: actions.setSourceViewportForReferenceLinesTool,\n },\n storePresentation: {\n commandFn: actions.storePresentation,\n },\n setToolbarToggled: {\n commandFn: actions.setToolbarToggled,\n },\n cleanUpCrosshairs: {\n commandFn: actions.cleanUpCrosshairs,\n },\n };\n\n return {\n actions,\n definitions,\n defaultContext: 'CORNERSTONE',\n };\n}\n\nexport default commandsModule;\n","import { Types } from '@ohif/core';\n\nconst mpr: Types.HangingProtocol.Protocol = {\n id: 'mpr',\n name: 'Multi-Planar Reconstruction',\n locked: true,\n createdDate: '2021-02-23',\n modifiedDate: '2023-08-15',\n availableTo: {},\n editableBy: {},\n // Unknown number of priors referenced - so just match any study\n numberOfPriorsReferenced: 0,\n protocolMatchingRules: [],\n imageLoadStrategy: 'nth',\n callbacks: {\n // Switches out of MPR mode when the layout change button is used\n onLayoutChange: [\n {\n commandName: 'toggleHangingProtocol',\n commandOptions: { protocolId: 'mpr' },\n context: 'DEFAULT',\n },\n ],\n // Turns off crosshairs when switching out of MPR mode\n onProtocolExit: [\n {\n commandName: 'cleanUpCrosshairs',\n },\n ],\n },\n displaySetSelectors: {\n activeDisplaySet: {\n seriesMatchingRules: [\n {\n weight: 1,\n attribute: 'isReconstructable',\n constraint: {\n equals: {\n value: true,\n },\n },\n required: true,\n },\n ],\n },\n },\n stages: [\n {\n name: 'MPR 1x3',\n viewportStructure: {\n layoutType: 'grid',\n properties: {\n rows: 1,\n columns: 3,\n layoutOptions: [\n {\n x: 0,\n y: 0,\n width: 1 / 3,\n height: 1,\n },\n {\n x: 1 / 3,\n y: 0,\n width: 1 / 3,\n height: 1,\n },\n {\n x: 2 / 3,\n y: 0,\n width: 1 / 3,\n height: 1,\n },\n ],\n },\n },\n viewports: [\n {\n viewportOptions: {\n viewportId: 'mpr-axial',\n toolGroupId: 'mpr',\n viewportType: 'volume',\n orientation: 'axial',\n initialImageOptions: {\n preset: 'middle',\n },\n syncGroups: [\n {\n type: 'voi',\n id: 'mpr',\n source: true,\n target: true,\n },\n ],\n },\n displaySets: [\n {\n id: 'activeDisplaySet',\n },\n ],\n },\n {\n viewportOptions: {\n viewportId: 'mpr-sagittal',\n toolGroupId: 'mpr',\n viewportType: 'volume',\n orientation: 'sagittal',\n initialImageOptions: {\n preset: 'middle',\n },\n syncGroups: [\n {\n type: 'voi',\n id: 'mpr',\n source: true,\n target: true,\n },\n ],\n },\n displaySets: [\n {\n id: 'activeDisplaySet',\n },\n ],\n },\n {\n viewportOptions: {\n viewportId: 'mpr-coronal',\n toolGroupId: 'mpr',\n viewportType: 'volume',\n orientation: 'coronal',\n initialImageOptions: {\n preset: 'middle',\n },\n syncGroups: [\n {\n type: 'voi',\n id: 'mpr',\n source: true,\n target: true,\n },\n ],\n },\n displaySets: [\n {\n id: 'activeDisplaySet',\n },\n ],\n },\n ],\n },\n ],\n};\n\nconst mprAnd3DVolumeViewport = {\n id: 'mprAnd3DVolumeViewport',\n locked: true,\n name: 'mpr',\n createdDate: '2023-03-15T10:29:44.894Z',\n modifiedDate: '2023-03-15T10:29:44.894Z',\n availableTo: {},\n editableBy: {},\n protocolMatchingRules: [],\n imageLoadStrategy: 'interleaveCenter',\n displaySetSelectors: {\n mprDisplaySet: {\n seriesMatchingRules: [\n {\n weight: 1,\n attribute: 'isReconstructable',\n constraint: {\n equals: {\n value: true,\n },\n },\n required: true,\n },\n {\n attribute: 'Modality',\n constraint: {\n equals: {\n value: 'CT',\n },\n },\n required: true,\n },\n ],\n },\n },\n stages: [\n {\n id: 'mpr3Stage',\n name: 'mpr',\n viewportStructure: {\n layoutType: 'grid',\n properties: {\n rows: 2,\n columns: 2,\n },\n },\n viewports: [\n {\n viewportOptions: {\n toolGroupId: 'mpr',\n viewportType: 'volume',\n orientation: 'axial',\n initialImageOptions: {\n preset: 'middle',\n },\n syncGroups: [\n {\n type: 'voi',\n id: 'mpr',\n source: true,\n target: true,\n },\n ],\n },\n displaySets: [\n {\n id: 'mprDisplaySet',\n },\n ],\n },\n {\n viewportOptions: {\n toolGroupId: 'volume3d',\n viewportType: 'volume3d',\n orientation: 'coronal',\n customViewportProps: {\n hideOverlays: true,\n },\n },\n displaySets: [\n {\n id: 'mprDisplaySet',\n options: {\n displayPreset: 'CT-Bone',\n },\n },\n ],\n },\n {\n viewportOptions: {\n toolGroupId: 'mpr',\n viewportType: 'volume',\n orientation: 'coronal',\n initialImageOptions: {\n preset: 'middle',\n },\n syncGroups: [\n {\n type: 'voi',\n id: 'mpr',\n source: true,\n target: true,\n },\n ],\n },\n displaySets: [\n {\n id: 'mprDisplaySet',\n },\n ],\n },\n {\n viewportOptions: {\n toolGroupId: 'mpr',\n viewportType: 'volume',\n orientation: 'sagittal',\n initialImageOptions: {\n preset: 'middle',\n },\n syncGroups: [\n {\n type: 'voi',\n id: 'mpr',\n source: true,\n target: true,\n },\n ],\n },\n displaySets: [\n {\n id: 'mprDisplaySet',\n },\n ],\n },\n ],\n },\n ],\n};\n\nfunction getHangingProtocolModule() {\n return [\n {\n name: mpr.id,\n protocol: mpr,\n },\n {\n name: mprAnd3DVolumeViewport.id,\n protocol: mprAnd3DVolumeViewport,\n },\n ];\n}\n\nexport default getHangingProtocolModule;\n","import { ToolGroupManager, Enums, Types } from '@cornerstonejs/tools';\n\nimport { Types as OhifTypes, pubSubServiceInterface } from '@ohif/core';\nimport getActiveViewportEnabledElement from '../../utils/getActiveViewportEnabledElement';\n\nconst EVENTS = {\n VIEWPORT_ADDED: 'event::cornerstone::toolgroupservice:viewportadded',\n TOOLGROUP_CREATED: 'event::cornerstone::toolgroupservice:toolgroupcreated',\n};\n\ntype Tool = {\n toolName: string;\n bindings?: typeof Enums.MouseBindings | Enums.KeyboardBindings;\n};\n\ntype Tools = {\n active: Tool[];\n passive?: Tool[];\n enabled?: Tool[];\n disabled?: Tool[];\n};\n\nexport default class ToolGroupService {\n public static REGISTRATION = {\n name: 'toolGroupService',\n altName: 'ToolGroupService',\n create: ({ servicesManager }: OhifTypes.Extensions.ExtensionParams): ToolGroupService => {\n return new ToolGroupService(servicesManager);\n },\n };\n\n serviceManager: any;\n private toolGroupIds: Set = new Set();\n /**\n * Service-specific\n */\n listeners: { [key: string]: Function[] };\n EVENTS: { [key: string]: string };\n\n constructor(serviceManager) {\n const { cornerstoneViewportService, viewportGridService } = serviceManager.services;\n this.cornerstoneViewportService = cornerstoneViewportService;\n this.viewportGridService = viewportGridService;\n this.listeners = {};\n this.EVENTS = EVENTS;\n Object.assign(this, pubSubServiceInterface);\n }\n\n onModeExit() {\n this.destroy();\n }\n\n /**\n * Retrieves a tool group from the ToolGroupManager by tool group ID.\n * If no tool group ID is provided, it retrieves the tool group of the active viewport.\n * @param toolGroupId - Optional ID of the tool group to retrieve.\n * @returns The tool group or undefined if it is not found.\n */\n public getToolGroup(toolGroupId?: string): Types.IToolGroup | void {\n let toolGroupIdToUse = toolGroupId;\n\n if (!toolGroupIdToUse) {\n // Use the active viewport's tool group if no tool group id is provided\n const enabledElement = getActiveViewportEnabledElement(this.viewportGridService);\n\n if (!enabledElement) {\n return;\n }\n\n const { renderingEngineId, viewportId } = enabledElement;\n const toolGroup = ToolGroupManager.getToolGroupForViewport(viewportId, renderingEngineId);\n\n if (!toolGroup) {\n console.warn(\n 'No tool group found for viewportId:',\n viewportId,\n 'and renderingEngineId:',\n renderingEngineId\n );\n return;\n }\n\n toolGroupIdToUse = toolGroup.id;\n }\n\n const toolGroup = ToolGroupManager.getToolGroup(toolGroupIdToUse);\n return toolGroup;\n }\n\n public getToolGroupIds(): string[] {\n return Array.from(this.toolGroupIds);\n }\n\n public getToolGroupForViewport(viewportId: string): Types.IToolGroup | void {\n const renderingEngine = this.cornerstoneViewportService.getRenderingEngine();\n return ToolGroupManager.getToolGroupForViewport(viewportId, renderingEngine.id);\n }\n\n public getActiveToolForViewport(viewportId: string): string {\n const toolGroup = this.getToolGroupForViewport(viewportId);\n if (!toolGroup) {\n return;\n }\n\n return toolGroup.getActivePrimaryMouseButtonTool();\n }\n\n public destroy() {\n ToolGroupManager.destroy();\n this.toolGroupIds = new Set();\n }\n\n public destroyToolGroup(toolGroupId: string) {\n ToolGroupManager.destroyToolGroup(toolGroupId);\n this.toolGroupIds.delete(toolGroupId);\n }\n\n public removeViewportFromToolGroup(\n viewportId: string,\n renderingEngineId: string,\n deleteToolGroupIfEmpty?: boolean\n ): void {\n const toolGroup = ToolGroupManager.getToolGroupForViewport(viewportId, renderingEngineId);\n\n if (!toolGroup) {\n return;\n }\n\n toolGroup.removeViewports(renderingEngineId, viewportId);\n\n const viewportIds = toolGroup.getViewportIds();\n\n if (viewportIds.length === 0 && deleteToolGroupIfEmpty) {\n ToolGroupManager.destroyToolGroup(toolGroup.id);\n }\n }\n\n public addViewportToToolGroup(\n viewportId: string,\n renderingEngineId: string,\n toolGroupId?: string\n ): void {\n if (!toolGroupId) {\n // If toolGroupId is not provided, add the viewport to all toolGroups\n const toolGroups = ToolGroupManager.getAllToolGroups();\n toolGroups.forEach(toolGroup => {\n toolGroup.addViewport(viewportId, renderingEngineId);\n });\n } else {\n let toolGroup = ToolGroupManager.getToolGroup(toolGroupId);\n if (!toolGroup) {\n toolGroup = this.createToolGroup(toolGroupId);\n }\n\n toolGroup.addViewport(viewportId, renderingEngineId);\n }\n\n this._broadcastEvent(EVENTS.VIEWPORT_ADDED, {\n viewportId,\n toolGroupId,\n });\n }\n\n public createToolGroup(toolGroupId: string): Types.IToolGroup {\n if (this.getToolGroup(toolGroupId)) {\n throw new Error(`ToolGroup ${toolGroupId} already exists`);\n }\n\n // if the toolGroup doesn't exist, create it\n const toolGroup = ToolGroupManager.createToolGroup(toolGroupId);\n this.toolGroupIds.add(toolGroupId);\n\n this._broadcastEvent(EVENTS.TOOLGROUP_CREATED, {\n toolGroupId,\n });\n\n return toolGroup;\n }\n\n public addToolsToToolGroup(toolGroupId: string, tools: Array, configs: any = {}): void {\n const toolGroup = ToolGroupManager.getToolGroup(toolGroupId);\n // this.changeConfigurationIfNecessary(toolGroup, volumeId);\n this._addTools(toolGroup, tools, configs);\n this._setToolsMode(toolGroup, tools);\n }\n\n public createToolGroupAndAddTools(toolGroupId: string, tools: Array): Types.IToolGroup {\n const toolGroup = this.createToolGroup(toolGroupId);\n this.addToolsToToolGroup(toolGroupId, tools);\n return toolGroup;\n }\n\n /**\n private changeConfigurationIfNecessary(toolGroup, volumeUID) {\n // handle specific assignment for volumeUID (e.g., fusion)\n const toolInstances = toolGroup._toolInstances;\n // Object.values(toolInstances).forEach(toolInstance => {\n // if (toolInstance.configuration) {\n // toolInstance.configuration.volumeUID = volumeUID;\n // }\n // });\n }\n */\n\n /**\n * Get the tool's configuration based on the tool name and tool group id\n * @param toolGroupId - The id of the tool group that the tool instance belongs to.\n * @param toolName - The name of the tool\n * @returns The configuration of the tool.\n */\n public getToolConfiguration(toolGroupId: string, toolName: string) {\n const toolGroup = ToolGroupManager.getToolGroup(toolGroupId);\n if (!toolGroup) {\n return null;\n }\n\n const tool = toolGroup.getToolInstance(toolName);\n if (!tool) {\n return null;\n }\n\n return tool.configuration;\n }\n\n /**\n * Set the tool instance configuration. This will update the tool instance configuration\n * on the toolGroup\n * @param toolGroupId - The id of the tool group that the tool instance belongs to.\n * @param toolName - The name of the tool\n * @param config - The configuration object that you want to set.\n */\n public setToolConfiguration(toolGroupId, toolName, config) {\n const toolGroup = ToolGroupManager.getToolGroup(toolGroupId);\n const toolInstance = toolGroup.getToolInstance(toolName);\n toolInstance.configuration = config;\n }\n\n private _setToolsMode(toolGroup, tools) {\n const { active, passive, enabled, disabled } = tools;\n\n if (active) {\n active.forEach(({ toolName, bindings }) => {\n toolGroup.setToolActive(toolName, { bindings });\n });\n }\n\n if (passive) {\n passive.forEach(({ toolName }) => {\n toolGroup.setToolPassive(toolName);\n });\n }\n\n if (enabled) {\n enabled.forEach(({ toolName }) => {\n toolGroup.setToolEnabled(toolName);\n });\n }\n\n if (disabled) {\n disabled.forEach(({ toolName }) => {\n toolGroup.setToolDisabled(toolName);\n });\n }\n }\n\n private _addTools(toolGroup, tools) {\n const addTools = tools => {\n tools.forEach(({ toolName, parentTool, configuration }) => {\n if (parentTool) {\n toolGroup.addToolInstance(toolName, parentTool, {\n ...configuration,\n });\n } else {\n toolGroup.addTool(toolName, { ...configuration });\n }\n });\n };\n\n if (tools.active) {\n addTools(tools.active);\n }\n\n if (tools.passive) {\n addTools(tools.passive);\n }\n\n if (tools.enabled) {\n addTools(tools.enabled);\n }\n\n if (tools.disabled) {\n addTools(tools.disabled);\n }\n }\n}\n","import ToolGroupService from './ToolGroupService';\n\nexport default ToolGroupService;\n","import { synchronizers, SynchronizerManager, Synchronizer } from '@cornerstonejs/tools';\n\nimport { pubSubServiceInterface, Types, ServicesManager } from '@ohif/core';\n\nconst EVENTS = {\n TOOL_GROUP_CREATED: 'event::cornerstone::syncgroupservice:toolgroupcreated',\n};\n\n/**\n * @params options - are an optional set of options associated with the first\n * sync group declared.\n */\nexport type SyncCreator = (id: string, options?: Record) => Synchronizer;\n\nexport type SyncGroup = {\n type: string;\n id?: string;\n // Source and target default to true if not specified\n source?: boolean;\n target?: boolean;\n options?: Record;\n};\n\nconst POSITION = 'cameraposition';\nconst VOI = 'voi';\nconst ZOOMPAN = 'zoompan';\nconst STACKIMAGE = 'stackimage';\n\nconst asSyncGroup = (syncGroup: string | SyncGroup): SyncGroup =>\n typeof syncGroup === 'string' ? { type: syncGroup } : syncGroup;\n\nexport default class SyncGroupService {\n static REGISTRATION = {\n name: 'syncGroupService',\n altName: 'SyncGroupService',\n create: ({ servicesManager }: Types.Extensions.ExtensionParams): SyncGroupService => {\n return new SyncGroupService(servicesManager);\n },\n };\n\n servicesManager: ServicesManager;\n listeners: { [key: string]: (...args: any[]) => void } = {};\n EVENTS: { [key: string]: string };\n synchronizerCreators: Record = {\n [POSITION]: synchronizers.createCameraPositionSynchronizer,\n [VOI]: synchronizers.createVOISynchronizer,\n [ZOOMPAN]: synchronizers.createZoomPanSynchronizer,\n [STACKIMAGE]: synchronizers.createStackImageSynchronizer,\n };\n\n constructor(serviceManager: ServicesManager) {\n this.servicesManager = serviceManager;\n this.listeners = {};\n this.EVENTS = EVENTS;\n //\n Object.assign(this, pubSubServiceInterface);\n }\n\n private _createSynchronizer(type: string, id: string, options): Synchronizer | undefined {\n const syncCreator = this.synchronizerCreators[type.toLowerCase()];\n if (syncCreator) {\n return syncCreator(id, options);\n } else {\n console.warn('Unknown synchronizer type', type, id);\n }\n }\n\n /**\n * Creates a synchronizer type.\n * @param type is the type of the synchronizer to create\n * @param creator\n */\n public addSynchronizerType(type: string, creator: SyncCreator): void {\n this.synchronizerCreators[type.toLowerCase()] = creator;\n }\n\n protected _getOrCreateSynchronizer(\n type: string,\n id: string,\n options: Record\n ): Synchronizer | undefined {\n let synchronizer = SynchronizerManager.getSynchronizer(id);\n\n if (!synchronizer) {\n synchronizer = this._createSynchronizer(type, id, options);\n }\n return synchronizer;\n }\n\n public addViewportToSyncGroup(\n viewportId: string,\n renderingEngineId: string,\n syncGroups?: SyncGroup | string | SyncGroup[] | string[]\n ): void {\n if (!syncGroups) {\n return;\n }\n\n const syncGroupsArray = Array.isArray(syncGroups) ? syncGroups : [syncGroups];\n\n syncGroupsArray.forEach(syncGroup => {\n const syncGroupObj = asSyncGroup(syncGroup);\n const { type, target = true, source = true, options = {}, id = type } = syncGroupObj;\n\n const synchronizer = this._getOrCreateSynchronizer(type, id, options);\n synchronizer.setOptions(viewportId, options);\n\n const viewportInfo = { viewportId, renderingEngineId };\n if (target && source) {\n synchronizer.add(viewportInfo);\n return;\n } else if (source) {\n synchronizer.addSource(viewportInfo);\n } else if (target) {\n synchronizer.addTarget(viewportInfo);\n }\n });\n }\n\n public destroy(): void {\n SynchronizerManager.destroy();\n }\n\n public removeViewportFromSyncGroup(\n viewportId: string,\n renderingEngineId: string,\n syncGroupId?: string\n ): void {\n const synchronizers = SynchronizerManager.getAllSynchronizers();\n\n const filteredSynchronizers = syncGroupId\n ? synchronizers.filter(s => s.id === syncGroupId)\n : synchronizers;\n\n filteredSynchronizers.forEach(synchronizer => {\n if (!synchronizer) {\n return;\n }\n\n synchronizer.remove({\n viewportId,\n renderingEngineId,\n });\n\n // check if any viewport is left in any of the sync groups, if not, delete that sync group\n const sourceViewports = synchronizer.getSourceViewports();\n const targetViewports = synchronizer.getTargetViewports();\n\n if (!sourceViewports.length && !targetViewports.length) {\n SynchronizerManager.destroySynchronizer(synchronizer.id);\n }\n });\n }\n}\n","import SyncGroupService from './SyncGroupService';\n\nexport default SyncGroupService;\n","/**\n * It is a bell curved function that uses ease in out quadratic for css\n * transition timing function for each side of the curve.\n *\n * @param {number} x - The current time, in the range [0, 1].\n * @param {number} baseline - The baseline value to start from and return to.\n * @returns the value of the transition at time x.\n */\nexport function easeInOutBell(x: number, baseline: number): number {\n const alpha = 1 - baseline;\n\n // prettier-ignore\n if (x < 1 / 4) {\n return 4 * Math.pow(2 * x, 3) * alpha + baseline;\n } else if (x < 1 / 2) {\n return (1 - Math.pow(-4 * x + 2, 3) / 2) * alpha + baseline;\n } else if (x < 3 / 4) {\n return (1 - Math.pow(4 * x - 2, 3) / 2) * alpha + baseline;\n } else {\n return (- 4 * Math.pow(2 * x - 2, 3)) * alpha + baseline;\n }\n}\n\n/**\n * A reversed bell curved function that starts from 1 and goes to baseline and\n * come back to 1 again. It uses ease in out quadratic for css transition\n * timing function for each side of the curve.\n *\n * @param {number} x - The current time, in the range [0, 1].\n * @param {number} baseline - The baseline value to start from and return to.\n * @returns the value of the transition at time x.\n */\nexport function reverseEaseInOutBell(x: number, baseline: number): number {\n const y = easeInOutBell(x, baseline);\n return -y + 1 + baseline;\n}\n","import cloneDeep from 'lodash.clonedeep';\n\nimport { Types as OhifTypes, ServicesManager, PubSubService } from '@ohif/core';\nimport {\n cache,\n Enums as csEnums,\n geometryLoader,\n eventTarget,\n getEnabledElementByIds,\n utilities as csUtils,\n volumeLoader,\n} from '@cornerstonejs/core';\nimport {\n CONSTANTS as cstConstants,\n Enums as csToolsEnums,\n segmentation as cstSegmentation,\n Types as cstTypes,\n utilities as cstUtils,\n} from '@cornerstonejs/tools';\nimport isEqual from 'lodash.isequal';\nimport { Types as ohifTypes } from '@ohif/core';\nimport { easeInOutBell, reverseEaseInOutBell } from '../../utils/transitions';\nimport { Segment, Segmentation, SegmentationConfig } from './SegmentationServiceTypes';\nimport { mapROIContoursToRTStructData } from './RTSTRUCT/mapROIContoursToRTStructData';\n\nconst { COLOR_LUT } = cstConstants;\nconst LABELMAP = csToolsEnums.SegmentationRepresentations.Labelmap;\nconst CONTOUR = csToolsEnums.SegmentationRepresentations.Contour;\n\nconst EVENTS = {\n // fired when the segmentation is updated (e.g. when a segment is added, removed, or modified, locked, visibility changed etc.)\n SEGMENTATION_UPDATED: 'event::segmentation_updated',\n // fired when the segmentation data (e.g., labelmap pixels) is modified\n SEGMENTATION_DATA_MODIFIED: 'event::segmentation_data_modified',\n // fired when the segmentation is added to the cornerstone\n SEGMENTATION_ADDED: 'event::segmentation_added',\n // fired when the segmentation is removed\n SEGMENTATION_REMOVED: 'event::segmentation_removed',\n // fired when the configuration for the segmentation is changed (e.g., brush size, render fill, outline thickness, etc.)\n SEGMENTATION_CONFIGURATION_CHANGED: 'event::segmentation_configuration_changed',\n // fired when the active segment is loaded in SEG or RTSTRUCT\n SEGMENT_LOADING_COMPLETE: 'event::segment_loading_complete',\n // for all segments\n SEGMENTATION_LOADING_COMPLETE: 'event::segmentation_loading_complete',\n};\n\nconst VALUE_TYPES = {};\n\nconst SEGMENT_CONSTANT = {\n opacity: 255,\n isVisible: true,\n isLocked: false,\n};\n\nconst VOLUME_LOADER_SCHEME = 'cornerstoneStreamingImageVolume';\n\nclass SegmentationService extends PubSubService {\n static REGISTRATION = {\n name: 'segmentationService',\n altName: 'SegmentationService',\n create: ({ servicesManager }: OhifTypes.Extensions.ExtensionParams): SegmentationService => {\n return new SegmentationService({ servicesManager });\n },\n };\n\n segmentations: Record;\n readonly servicesManager: ServicesManager;\n highlightIntervalId = null;\n readonly EVENTS = EVENTS;\n\n constructor({ servicesManager }) {\n super(EVENTS);\n this.segmentations = {};\n\n this.servicesManager = servicesManager;\n\n this._initSegmentationService();\n }\n\n public destroy = () => {\n eventTarget.removeEventListener(\n csToolsEnums.Events.SEGMENTATION_MODIFIED,\n this._onSegmentationModifiedFromSource\n );\n\n eventTarget.removeEventListener(\n csToolsEnums.Events.SEGMENTATION_DATA_MODIFIED,\n this._onSegmentationDataModified\n );\n\n // remove the segmentations from the cornerstone\n Object.keys(this.segmentations).forEach(segmentationId => {\n this._removeSegmentationFromCornerstone(segmentationId);\n });\n\n this.segmentations = {};\n this.listeners = {};\n };\n\n /**\n * Adds a new segment to the specified segmentation.\n * @param segmentationId - The ID of the segmentation to add the segment to.\n * @param config - An object containing the configuration options for the new segment.\n * - segmentIndex: (optional) The index of the segment to add. If not provided, the next available index will be used.\n * - toolGroupId: (optional) The ID of the tool group to associate the new segment with. If not provided, the first available tool group will be used.\n * - properties: (optional) An object containing the properties of the new segment.\n * - label: (optional) The label of the new segment. If not provided, a default label will be used.\n * - color: (optional) The color of the new segment in RGB format. If not provided, a default color will be used.\n * - opacity: (optional) The opacity of the new segment. If not provided, a default opacity will be used.\n * - visibility: (optional) Whether the new segment should be visible. If not provided, the segment will be visible by default.\n * - isLocked: (optional) Whether the new segment should be locked for editing. If not provided, the segment will not be locked by default.\n * - active: (optional) Whether the new segment should be the active segment to be edited. If not provided, the segment will not be active by default.\n */\n public addSegment(\n segmentationId: string,\n config: {\n segmentIndex?: number;\n toolGroupId?: string;\n properties?: {\n label?: string;\n color?: ohifTypes.RGB;\n opacity?: number;\n visibility?: boolean;\n isLocked?: boolean;\n active?: boolean;\n };\n } = {}\n ): void {\n if (config?.segmentIndex === 0) {\n throw new Error('Segment index 0 is reserved for \"no label\"');\n }\n\n const toolGroupId = config.toolGroupId ?? this._getApplicableToolGroupId();\n\n const { segmentationRepresentationUID, segmentation } = this._getSegmentationInfo(\n segmentationId,\n toolGroupId\n );\n\n let segmentIndex = config.segmentIndex;\n if (!segmentIndex) {\n // grab the next available segment index\n segmentIndex = segmentation.segments.length === 0 ? 1 : segmentation.segments.length;\n }\n\n if (this._getSegmentInfo(segmentation, segmentIndex)) {\n throw new Error(`Segment ${segmentIndex} already exists`);\n }\n\n const rgbaColor = cstSegmentation.config.color.getColorForSegmentIndex(\n toolGroupId,\n segmentationRepresentationUID,\n segmentIndex\n );\n\n segmentation.segments[segmentIndex] = {\n label: config.properties?.label ?? `Segment ${segmentIndex}`,\n segmentIndex: segmentIndex,\n color: [rgbaColor[0], rgbaColor[1], rgbaColor[2]],\n opacity: rgbaColor[3],\n isVisible: true,\n isLocked: false,\n };\n\n segmentation.segmentCount++;\n\n // make the newly added segment the active segment\n this._setActiveSegment(segmentationId, segmentIndex);\n\n const suppressEvents = true;\n if (config.properties !== undefined) {\n const { color: newColor, opacity, isLocked, visibility, active } = config.properties;\n\n if (newColor !== undefined) {\n this._setSegmentColor(segmentationId, segmentIndex, newColor, toolGroupId, suppressEvents);\n }\n\n if (opacity !== undefined) {\n this._setSegmentOpacity(segmentationId, segmentIndex, opacity, toolGroupId, suppressEvents);\n }\n\n if (visibility !== undefined) {\n this._setSegmentVisibility(\n segmentationId,\n segmentIndex,\n visibility,\n toolGroupId,\n suppressEvents\n );\n }\n\n if (active === true) {\n this._setActiveSegment(segmentationId, segmentIndex, suppressEvents);\n }\n\n if (isLocked !== undefined) {\n this._setSegmentLocked(segmentationId, segmentIndex, isLocked, suppressEvents);\n }\n }\n\n if (segmentation.activeSegmentIndex === null) {\n this._setActiveSegment(segmentationId, segmentIndex, suppressEvents);\n }\n\n // Todo: this includes non-hydrated segmentations which might not be\n // persisted in the store\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n }\n\n public removeSegment(segmentationId: string, segmentIndex: number): void {\n const segmentation = this.getSegmentation(segmentationId);\n\n if (segmentation === undefined) {\n throw new Error(`no segmentation for segmentationId: ${segmentationId}`);\n }\n\n if (segmentIndex === 0) {\n throw new Error('Segment index 0 is reserved for \"no label\"');\n }\n\n if (!this._getSegmentInfo(segmentation, segmentIndex)) {\n return;\n }\n\n segmentation.segmentCount--;\n\n segmentation.segments[segmentIndex] = null;\n\n // Get volume and delete the labels\n // Todo: handle other segmentations other than labelmap\n const labelmapVolume = this.getLabelmapVolume(segmentationId);\n\n const { dimensions } = labelmapVolume;\n const scalarData = labelmapVolume.getScalarData();\n\n // Set all values of this segment to zero and get which frames have been edited.\n const frameLength = dimensions[0] * dimensions[1];\n const numFrames = dimensions[2];\n\n let voxelIndex = 0;\n\n const modifiedFrames = new Set() as Set;\n\n for (let frame = 0; frame < numFrames; frame++) {\n for (let p = 0; p < frameLength; p++) {\n if (scalarData[voxelIndex] === segmentIndex) {\n scalarData[voxelIndex] = 0;\n modifiedFrames.add(frame);\n }\n\n voxelIndex++;\n }\n }\n\n const modifiedFramesArray: number[] = Array.from(modifiedFrames);\n\n // Trigger texture update of modified segmentation frames.\n cstSegmentation.triggerSegmentationEvents.triggerSegmentationDataModified(\n segmentationId,\n modifiedFramesArray\n );\n\n if (segmentation.activeSegmentIndex === segmentIndex) {\n const segmentIndices = Object.keys(segmentation.segments);\n\n const newActiveSegmentIndex = segmentIndices.length ? Number(segmentIndices[0]) : 1;\n\n this._setActiveSegment(segmentationId, newActiveSegmentIndex, true);\n }\n\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n }\n\n public setSegmentVisibility(\n segmentationId: string,\n segmentIndex: number,\n isVisible: boolean,\n toolGroupId?: string,\n suppressEvents = false\n ): void {\n this._setSegmentVisibility(\n segmentationId,\n segmentIndex,\n isVisible,\n toolGroupId,\n suppressEvents\n );\n }\n\n public setSegmentLocked(segmentationId: string, segmentIndex: number, isLocked: boolean): void {\n const suppressEvents = false;\n this._setSegmentLocked(segmentationId, segmentIndex, isLocked, suppressEvents);\n }\n\n /**\n * Toggles the locked state of a segment in a segmentation.\n * @param segmentationId - The ID of the segmentation.\n * @param segmentIndex - The index of the segment to toggle.\n */\n public toggleSegmentLocked(segmentationId: string, segmentIndex: number): void {\n const segmentation = this.getSegmentation(segmentationId);\n const segment = this._getSegmentInfo(segmentation, segmentIndex);\n const isLocked = !segment.isLocked;\n this._setSegmentLocked(segmentationId, segmentIndex, isLocked);\n }\n\n public setSegmentColor(\n segmentationId: string,\n segmentIndex: number,\n color: ohifTypes.RGB,\n toolGroupId?: string\n ): void {\n this._setSegmentColor(segmentationId, segmentIndex, color, toolGroupId);\n }\n\n public setSegmentRGBA = (\n segmentationId: string,\n segmentIndex: number,\n rgbaColor: cstTypes.Color,\n toolGroupId?: string\n ): void => {\n const segmentation = this.getSegmentation(segmentationId);\n\n if (segmentation === undefined) {\n throw new Error(`no segmentation for segmentationId: ${segmentationId}`);\n }\n\n const suppressEvents = true;\n this._setSegmentOpacity(\n segmentationId,\n segmentIndex,\n rgbaColor[3],\n toolGroupId,\n suppressEvents\n );\n\n this._setSegmentColor(\n segmentationId,\n segmentIndex,\n [rgbaColor[0], rgbaColor[1], rgbaColor[2]],\n toolGroupId,\n suppressEvents\n );\n\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n };\n\n public setSegmentOpacity(\n segmentationId: string,\n segmentIndex: number,\n opacity: number,\n toolGroupId?: string\n ): void {\n this._setSegmentOpacity(segmentationId, segmentIndex, opacity, toolGroupId);\n }\n\n public setActiveSegmentationForToolGroup(segmentationId: string, toolGroupId?: string): void {\n toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();\n\n const suppressEvents = false;\n this._setActiveSegmentationForToolGroup(segmentationId, toolGroupId, suppressEvents);\n }\n\n public setActiveSegment(segmentationId: string, segmentIndex: number): void {\n this._setActiveSegment(segmentationId, segmentIndex, false);\n }\n\n /**\n * Get all segmentations.\n *\n * * @param filterNonHydratedSegmentations - If true, only return hydrated segmentations\n * hydrated segmentations are those that have been loaded and persisted\n * in the state, but non hydrated segmentations are those that are\n * only created for the SEG displayset (SEG viewport) and the user might not\n * have loaded them yet fully.\n *\n\n * @return Array of segmentations\n */\n public getSegmentations(filterNonHydratedSegmentations = true): Segmentation[] {\n const segmentations = this._getSegmentations();\n\n return (\n segmentations &&\n segmentations.filter(segmentation => {\n return !filterNonHydratedSegmentations || segmentation.hydrated;\n })\n );\n }\n\n private _getSegmentations(): Segmentation[] {\n const segmentations = this.arrayOfObjects(this.segmentations);\n return segmentations && segmentations.map(m => this.segmentations[Object.keys(m)[0]]);\n }\n\n public getActiveSegmentation(): Segmentation {\n const segmentations = this.getSegmentations();\n\n return segmentations.find(segmentation => segmentation.isActive);\n }\n\n public getActiveSegment() {\n const activeSegmentation = this.getActiveSegmentation();\n const { activeSegmentIndex, segments } = activeSegmentation;\n\n if (activeSegmentIndex === null) {\n return;\n }\n\n return segments[activeSegmentIndex];\n }\n\n /**\n * Get specific segmentation by its id.\n *\n * @param segmentationId If of the segmentation\n * @return segmentation instance\n */\n public getSegmentation(segmentationId: string): Segmentation {\n return this.segmentations[segmentationId];\n }\n\n public addOrUpdateSegmentation(\n segmentation: Segmentation,\n suppressEvents = false,\n notYetUpdatedAtSource = false\n ): string {\n const { id: segmentationId } = segmentation;\n let cachedSegmentation = this.segmentations[segmentationId];\n if (cachedSegmentation) {\n // Update the segmentation (mostly for assigning metadata/labels)\n Object.assign(cachedSegmentation, segmentation);\n\n this._updateCornerstoneSegmentations({\n segmentationId,\n notYetUpdatedAtSource,\n });\n\n if (!suppressEvents) {\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation: cachedSegmentation,\n });\n }\n\n return segmentationId;\n }\n\n const representationType = segmentation.type;\n const representationData = segmentation.representationData[representationType];\n cstSegmentation.addSegmentations([\n {\n segmentationId,\n representation: {\n type: representationType,\n data: {\n ...representationData,\n },\n },\n },\n ]);\n\n // if first segmentation, we can use the default colorLUT, otherwise\n // we need to generate a new one and use a new colorLUT\n const colorLUTIndex = 0;\n if (Object.keys(this.segmentations).length !== 0) {\n const newColorLUT = this.generateNewColorLUT();\n const colorLUTIndex = this.getNextColorLUTIndex();\n cstSegmentation.config.color.addColorLUT(newColorLUT, colorLUTIndex);\n }\n\n this.segmentations[segmentationId] = {\n ...segmentation,\n label: segmentation.label || '',\n segments: segmentation.segments || [null],\n activeSegmentIndex: segmentation.activeSegmentIndex ?? null,\n segmentCount: segmentation.segmentCount ?? 0,\n isActive: false,\n isVisible: true,\n colorLUTIndex,\n };\n\n cachedSegmentation = this.segmentations[segmentationId];\n\n this._updateCornerstoneSegmentations({\n segmentationId,\n notYetUpdatedAtSource: true,\n });\n\n if (!suppressEvents) {\n this._broadcastEvent(this.EVENTS.SEGMENTATION_ADDED, {\n segmentation: cachedSegmentation,\n });\n }\n\n return cachedSegmentation.id;\n }\n\n public async createSegmentationForSEGDisplaySet(\n segDisplaySet,\n segmentationId?: string,\n suppressEvents = false\n ): Promise {\n // Todo: we only support creating labelmap for SEG displaySets for now\n const representationType = LABELMAP;\n\n segmentationId = segmentationId ?? segDisplaySet.displaySetInstanceUID;\n\n const defaultScheme = this._getDefaultSegmentationScheme();\n\n const segmentation: Segmentation = {\n ...defaultScheme,\n id: segmentationId,\n displaySetInstanceUID: segDisplaySet.displaySetInstanceUID,\n type: representationType,\n label: segDisplaySet.SeriesDescription,\n representationData: {\n [LABELMAP]: {\n volumeId: segmentationId,\n referencedVolumeId: segDisplaySet.referencedVolumeId,\n },\n },\n };\n\n const labelmap = this.getLabelmapVolume(segmentationId);\n const cachedSegmentation = this.getSegmentation(segmentationId);\n if (labelmap && cachedSegmentation) {\n // if the labelmap with the same segmentationId already exists, we can\n // just assume that the segmentation is already created and move on with\n // updating the state\n return this.addOrUpdateSegmentation(\n Object.assign(segmentation, cachedSegmentation),\n suppressEvents\n );\n }\n\n const { labelmapBufferArray, referencedVolumeId } = segDisplaySet;\n\n if (!labelmapBufferArray || !referencedVolumeId) {\n throw new Error('No labelmapBufferArray or referencedVolumeId found for the SEG displaySet');\n }\n\n // if the labelmap doesn't exist, we need to create it first from the\n // DICOM SEG displaySet data\n const referencedVolume = cache.getVolume(referencedVolumeId);\n\n if (!referencedVolume) {\n throw new Error(`No volume found for referencedVolumeId: ${referencedVolumeId}`);\n }\n\n // Force use of a Uint8Array SharedArrayBuffer for the segmentation to save space and so\n // it is easily compressible in worker thread.\n const derivedVolume = await volumeLoader.createAndCacheDerivedVolume(referencedVolumeId, {\n volumeId: segmentationId,\n targetBuffer: {\n type: 'Uint8Array',\n sharedArrayBuffer: window.SharedArrayBuffer,\n },\n });\n const derivedVolumeScalarData = derivedVolume.getScalarData();\n\n const segmentsInfo = segDisplaySet.segMetadata.data;\n derivedVolumeScalarData.set(new Uint8Array(labelmapBufferArray[0]));\n\n segmentation.segments = segmentsInfo.map((segmentInfo, segmentIndex) => {\n if (segmentIndex === 0) {\n return;\n }\n\n const {\n SegmentedPropertyCategoryCodeSequence,\n SegmentNumber,\n SegmentLabel,\n SegmentAlgorithmType,\n SegmentAlgorithmName,\n SegmentedPropertyTypeCodeSequence,\n rgba,\n } = segmentInfo;\n\n const { x, y, z } = segDisplaySet.centroids.get(segmentIndex);\n const centerWorld = derivedVolume.imageData.indexToWorld([x, y, z]);\n\n segmentation.cachedStats = {\n ...segmentation.cachedStats,\n segmentCenter: {\n ...segmentation.cachedStats.segmentCenter,\n [segmentIndex]: {\n center: {\n image: [x, y, z],\n world: centerWorld,\n },\n modifiedTime: segDisplaySet.SeriesDate,\n },\n },\n };\n\n return {\n label: SegmentLabel || `Segment ${SegmentNumber}`,\n segmentIndex: Number(SegmentNumber),\n category: SegmentedPropertyCategoryCodeSequence\n ? SegmentedPropertyCategoryCodeSequence.CodeMeaning\n : '',\n type: SegmentedPropertyTypeCodeSequence\n ? SegmentedPropertyTypeCodeSequence.CodeMeaning\n : '',\n algorithmType: SegmentAlgorithmType,\n algorithmName: SegmentAlgorithmName,\n color: rgba,\n opacity: 255,\n isVisible: true,\n isLocked: false,\n };\n });\n\n segmentation.segmentCount = segmentsInfo.length - 1;\n\n segDisplaySet.isLoaded = true;\n\n this._broadcastEvent(EVENTS.SEGMENTATION_LOADING_COMPLETE, {\n segmentationId,\n segDisplaySet,\n });\n\n return this.addOrUpdateSegmentation(segmentation, suppressEvents);\n }\n\n public async createSegmentationForRTDisplaySet(\n rtDisplaySet,\n segmentationId?: string,\n suppressEvents = false\n ): Promise {\n // Todo: we currently only have support for contour representation for initial\n // RT display\n const representationType = CONTOUR;\n segmentationId = segmentationId ?? rtDisplaySet.displaySetInstanceUID;\n const { structureSet } = rtDisplaySet;\n\n if (!structureSet) {\n throw new Error(\n 'To create the contours from RT displaySet, the displaySet should be loaded first, you can perform rtDisplaySet.load() before calling this method.'\n );\n }\n\n const defaultScheme = this._getDefaultSegmentationScheme();\n const rtDisplaySetUID = rtDisplaySet.displaySetInstanceUID;\n\n const allRTStructData = mapROIContoursToRTStructData(structureSet, rtDisplaySetUID);\n\n // sort by segmentIndex\n allRTStructData.sort((a, b) => a.segmentIndex - b.segmentIndex);\n\n const geometryIds = allRTStructData.map(({ geometryId }) => geometryId);\n\n const segmentation: Segmentation = {\n ...defaultScheme,\n id: segmentationId,\n displaySetInstanceUID: rtDisplaySetUID,\n type: representationType,\n label: rtDisplaySet.SeriesDescription,\n representationData: {\n [CONTOUR]: {\n geometryIds,\n },\n },\n };\n\n const cachedSegmentation = this.getSegmentation(segmentationId);\n\n if (cachedSegmentation) {\n // if the labelmap with the same segmentationId already exists, we can\n // just assume that the segmentation is already created and move on with\n // updating the state\n return this.addOrUpdateSegmentation(\n Object.assign(segmentation, cachedSegmentation),\n suppressEvents\n );\n }\n\n if (!structureSet.ROIContours?.length) {\n throw new Error(\n 'The structureSet does not contain any ROIContours. Please ensure the structureSet is loaded first.'\n );\n }\n const segmentsCachedStats = {};\n const initializeContour = async rtStructData => {\n const { data, id, color, segmentIndex, geometryId } = rtStructData;\n\n // catch error instead of failing to allow loading to continue\n try {\n const geometry = await geometryLoader.createAndCacheGeometry(geometryId, {\n geometryData: {\n data,\n id,\n color,\n frameOfReferenceUID: structureSet.frameOfReferenceUID,\n segmentIndex,\n },\n type: csEnums.GeometryType.CONTOUR,\n });\n\n const contourSet = geometry.data;\n const centroid = contourSet.getCentroid();\n\n segmentsCachedStats[segmentIndex] = {\n center: { world: centroid },\n modifiedTime: rtDisplaySet.SeriesDate, // we use the SeriesDate as the modifiedTime since this is the first time we are creating the segmentation\n };\n\n segmentation.segments[segmentIndex] = {\n label: id,\n segmentIndex,\n color,\n ...SEGMENT_CONSTANT,\n };\n\n const numInitialized = Object.keys(segmentsCachedStats).length;\n\n // Calculate percentage completed\n const percentComplete = Math.round((numInitialized / allRTStructData.length) * 100);\n\n this._broadcastEvent(EVENTS.SEGMENT_LOADING_COMPLETE, {\n percentComplete,\n // Note: this is not the geometryIds length since there might be\n // some missing ROINumbers\n numSegments: allRTStructData.length,\n });\n } catch (e) {\n console.warn(e);\n }\n };\n\n const promiseArray = [];\n\n for (let i = 0; i < allRTStructData.length; i++) {\n const promise = new Promise((resolve, reject) => {\n setTimeout(() => {\n initializeContour(allRTStructData[i]).then(() => {\n resolve();\n });\n }, 0);\n });\n\n promiseArray.push(promise);\n }\n\n await Promise.all(promiseArray);\n\n segmentation.segmentCount = allRTStructData.length;\n rtDisplaySet.isLoaded = true;\n\n segmentation.cachedStats = {\n ...segmentation.cachedStats,\n segmentCenter: {\n ...segmentation.cachedStats.segmentCenter,\n ...segmentsCachedStats,\n },\n };\n\n this._broadcastEvent(EVENTS.SEGMENTATION_LOADING_COMPLETE, {\n segmentationId,\n rtDisplaySet,\n });\n\n return this.addOrUpdateSegmentation(segmentation, suppressEvents);\n }\n\n // Todo: this should not run on the main thread\n public calculateCentroids = (\n segmentationId: string,\n segmentIndex?: number\n ): Map => {\n const segmentation = this.getSegmentation(segmentationId);\n const volume = this.getLabelmapVolume(segmentationId);\n const { dimensions, imageData } = volume;\n const scalarData = volume.getScalarData();\n const [dimX, dimY, numFrames] = dimensions;\n const frameLength = dimX * dimY;\n\n const segmentIndices = segmentIndex\n ? [segmentIndex]\n : segmentation.segments\n .filter(segment => segment?.segmentIndex)\n .map(segment => segment.segmentIndex);\n\n const segmentIndicesSet = new Set(segmentIndices);\n\n const centroids = new Map();\n for (const index of segmentIndicesSet) {\n centroids.set(index, { x: 0, y: 0, z: 0, count: 0 });\n }\n\n let voxelIndex = 0;\n for (let frame = 0; frame < numFrames; frame++) {\n for (let p = 0; p < frameLength; p++) {\n const segmentIndex = scalarData[voxelIndex++];\n if (segmentIndicesSet.has(segmentIndex)) {\n const centroid = centroids.get(segmentIndex);\n centroid.x += p % dimX;\n centroid.y += (p / dimX) | 0;\n centroid.z += frame;\n centroid.count++;\n }\n }\n }\n\n const result = new Map();\n for (const [index, centroid] of centroids) {\n const count = centroid.count;\n const normalizedCentroid = {\n x: centroid.x / count,\n y: centroid.y / count,\n z: centroid.z / count,\n };\n normalizedCentroid.world = imageData.indexToWorld([\n normalizedCentroid.x,\n normalizedCentroid.y,\n normalizedCentroid.z,\n ]);\n result.set(index, normalizedCentroid);\n }\n\n this.setCentroids(segmentationId, result);\n return result;\n };\n\n private setCentroids = (\n segmentationId: string,\n centroids: Map\n ): void => {\n const segmentation = this.getSegmentation(segmentationId);\n const imageData = this.getLabelmapVolume(segmentationId).imageData; // Assuming this method returns imageData\n\n if (!segmentation.cachedStats) {\n segmentation.cachedStats = { segmentCenter: {} };\n } else if (!segmentation.cachedStats.segmentCenter) {\n segmentation.cachedStats.segmentCenter = {};\n }\n\n for (const [segmentIndex, centroid] of centroids) {\n let world = centroid.world;\n\n // If world coordinates are not provided, calculate them\n if (!world || world.length === 0) {\n world = imageData.indexToWorld(centroid.image);\n }\n\n segmentation.cachedStats.segmentCenter[segmentIndex] = {\n center: {\n image: centroid.image,\n world: world,\n },\n };\n }\n\n this.addOrUpdateSegmentation(segmentation, true, true);\n };\n\n public jumpToSegmentCenter(\n segmentationId: string,\n segmentIndex: number,\n toolGroupId?: string,\n highlightAlpha = 0.9,\n highlightSegment = true,\n animationLength = 750,\n highlightHideOthers = false,\n highlightFunctionType = 'ease-in-out' // todo: make animation functions configurable from outside\n ): void {\n const { toolGroupService } = this.servicesManager.services;\n const center = this._getSegmentCenter(segmentationId, segmentIndex);\n\n if (!center?.world) {\n return;\n }\n\n const { world } = center;\n\n // todo: generalize\n toolGroupId = toolGroupId || this._getToolGroupIdsWithSegmentation(segmentationId);\n\n const toolGroups = [];\n\n if (Array.isArray(toolGroupId)) {\n toolGroupId.forEach(toolGroup => {\n toolGroups.push(toolGroupService.getToolGroup(toolGroup));\n });\n } else {\n toolGroups.push(toolGroupService.getToolGroup(toolGroupId));\n }\n\n toolGroups.forEach(toolGroup => {\n const viewportsInfo = toolGroup.getViewportsInfo();\n\n // @ts-ignore\n for (const { viewportId, renderingEngineId } of viewportsInfo) {\n const { viewport } = getEnabledElementByIds(viewportId, renderingEngineId);\n cstUtils.viewport.jumpToWorld(viewport, world);\n }\n\n if (highlightSegment) {\n this.highlightSegment(\n segmentationId,\n segmentIndex,\n toolGroup.id,\n highlightAlpha,\n animationLength,\n highlightHideOthers,\n highlightFunctionType\n );\n }\n });\n }\n\n public highlightSegment(\n segmentationId: string,\n segmentIndex: number,\n toolGroupId?: string,\n alpha = 0.9,\n animationLength = 750,\n hideOthers = true,\n highlightFunctionType = 'ease-in-out'\n ): void {\n if (this.highlightIntervalId) {\n clearInterval(this.highlightIntervalId);\n }\n\n const segmentation = this.getSegmentation(segmentationId);\n toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();\n\n const segmentationRepresentation = this._getSegmentationRepresentation(\n segmentationId,\n toolGroupId\n );\n\n const { type } = segmentationRepresentation;\n const { segments } = segmentation;\n\n const highlightFn =\n type === LABELMAP ? this._highlightLabelmap.bind(this) : this._highlightContour.bind(this);\n\n const adjustedAlpha = type === LABELMAP ? alpha : 1 - alpha;\n\n highlightFn(\n segmentIndex,\n adjustedAlpha,\n hideOthers,\n segments,\n toolGroupId,\n animationLength,\n segmentationRepresentation\n );\n }\n\n public createSegmentationForDisplaySet = async (\n displaySetInstanceUID: string,\n options?: {\n segmentationId: string;\n FrameOfReferenceUID: string;\n label: string;\n }\n ): Promise => {\n const { displaySetService } = this.servicesManager.services;\n\n const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);\n\n // Todo: we currently only support labelmap for segmentation for a displaySet\n const representationType = LABELMAP;\n\n const volumeId = this._getVolumeIdForDisplaySet(displaySet);\n\n const segmentationId = options?.segmentationId ?? `${csUtils.uuidv4()}`;\n\n // Force use of a Uint8Array SharedArrayBuffer for the segmentation to save space and so\n // it is easily compressible in worker thread.\n await volumeLoader.createAndCacheDerivedVolume(volumeId, {\n volumeId: segmentationId,\n targetBuffer: {\n type: 'Uint8Array',\n sharedArrayBuffer: window.SharedArrayBuffer,\n },\n });\n\n const defaultScheme = this._getDefaultSegmentationScheme();\n\n const segmentation: Segmentation = {\n ...defaultScheme,\n id: segmentationId,\n displaySetInstanceUID,\n label: options?.label,\n // We should set it as active by default, as it created for display\n isActive: true,\n type: representationType,\n FrameOfReferenceUID:\n options?.FrameOfReferenceUID || displaySet.instances?.[0]?.FrameOfReferenceUID,\n representationData: {\n LABELMAP: {\n volumeId: segmentationId,\n referencedVolumeId: volumeId, // Todo: this is so ugly\n },\n },\n };\n\n this.addOrUpdateSegmentation(segmentation);\n\n return segmentationId;\n };\n\n /**\n * Toggles the visibility of a segmentation in the state, and broadcasts the event.\n * Note: this method does not update the segmentation state in the source. It only\n * updates the state, and there should be separate listeners for that.\n * @param ids segmentation ids\n */\n public toggleSegmentationVisibility = (segmentationId: string): void => {\n this._toggleSegmentationVisibility(segmentationId, false);\n };\n\n public addSegmentationRepresentationToToolGroup = async (\n toolGroupId: string,\n segmentationId: string,\n hydrateSegmentation = false,\n representationType = csToolsEnums.SegmentationRepresentations.Labelmap,\n suppressEvents = false\n ): Promise => {\n const segmentation = this.getSegmentation(segmentationId);\n\n if (!segmentation) {\n throw new Error(`Segmentation with segmentationId ${segmentationId} not found.`);\n }\n\n if (hydrateSegmentation) {\n // hydrate the segmentation if it's not hydrated yet\n segmentation.hydrated = true;\n }\n\n const { colorLUTIndex } = segmentation;\n\n // Based on the segmentationId, set the colorLUTIndex.\n const segmentationRepresentationUIDs = await cstSegmentation.addSegmentationRepresentations(\n toolGroupId,\n [\n {\n segmentationId,\n type: representationType,\n },\n ]\n );\n\n // set the latest segmentation representation as active one\n this._setActiveSegmentationForToolGroup(\n segmentationId,\n toolGroupId,\n segmentationRepresentationUIDs[0]\n );\n\n cstSegmentation.config.color.setColorLUT(\n toolGroupId,\n segmentationRepresentationUIDs[0],\n colorLUTIndex\n );\n\n // add the segmentation segments properly\n for (const segment of segmentation.segments) {\n if (segment === null || segment === undefined) {\n continue;\n }\n\n const { segmentIndex, color, isLocked, isVisible: visibility, opacity } = segment;\n\n const suppressEvents = true;\n\n if (color !== undefined) {\n this._setSegmentColor(segmentationId, segmentIndex, color, toolGroupId, suppressEvents);\n }\n\n if (opacity !== undefined) {\n this._setSegmentOpacity(segmentationId, segmentIndex, opacity, toolGroupId, suppressEvents);\n }\n\n if (visibility !== undefined) {\n this._setSegmentVisibility(\n segmentationId,\n segmentIndex,\n visibility,\n toolGroupId,\n suppressEvents\n );\n }\n\n if (isLocked) {\n this._setSegmentLocked(segmentationId, segmentIndex, isLocked, suppressEvents);\n }\n }\n\n if (!suppressEvents) {\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n }\n };\n\n public setSegmentRGBAColor = (\n segmentationId: string,\n segmentIndex: number,\n rgbaColor,\n toolGroupId?: string\n ) => {\n const segmentation = this.getSegmentation(segmentationId);\n\n if (segmentation === undefined) {\n throw new Error(`no segmentation for segmentationId: ${segmentationId}`);\n }\n\n this._setSegmentOpacity(\n segmentationId,\n segmentIndex,\n rgbaColor[3],\n toolGroupId, // toolGroupId\n true\n );\n this._setSegmentColor(\n segmentationId,\n segmentIndex,\n [rgbaColor[0], rgbaColor[1], rgbaColor[2]],\n toolGroupId, // toolGroupId\n true\n );\n\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n };\n\n public getToolGroupIdsWithSegmentation = (segmentationId: string): string[] => {\n const toolGroupIds = cstSegmentation.state.getToolGroupIdsWithSegmentation(segmentationId);\n return toolGroupIds;\n };\n\n public hydrateSegmentation = (segmentationId: string, suppressEvents = false): void => {\n const segmentation = this.getSegmentation(segmentationId);\n\n if (!segmentation) {\n throw new Error(`Segmentation with segmentationId ${segmentationId} not found.`);\n }\n segmentation.hydrated = true;\n\n // Not all segmentations have dipslaysets, some of them are derived in the client\n this._setDisplaySetIsHydrated(segmentationId, true);\n\n if (!suppressEvents) {\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n }\n };\n\n private _setDisplaySetIsHydrated(displaySetUID: string, isHydrated: boolean): void {\n const { displaySetService } = this.servicesManager.services;\n const displaySet = displaySetService.getDisplaySetByUID(displaySetUID);\n\n if (!displaySet) {\n return;\n }\n\n displaySet.isHydrated = isHydrated;\n displaySetService.setDisplaySetMetadataInvalidated(displaySetUID, false);\n }\n\n private _highlightLabelmap(\n segmentIndex: number,\n alpha: number,\n hideOthers: boolean,\n segments: Segment[],\n toolGroupId: string,\n animationLength: number,\n segmentationRepresentation: cstTypes.ToolGroupSpecificRepresentation\n ) {\n const newSegmentSpecificConfig = {\n [segmentIndex]: {\n LABELMAP: {\n fillAlpha: alpha,\n },\n },\n };\n\n if (hideOthers) {\n for (let i = 0; i < segments.length; i++) {\n if (i !== segmentIndex) {\n newSegmentSpecificConfig[i] = {\n LABELMAP: {\n fillAlpha: 0,\n },\n };\n }\n }\n }\n\n const { fillAlpha } = this.getConfiguration(toolGroupId);\n\n let startTime: number = null;\n const animation = (timestamp: number) => {\n if (startTime === null) {\n startTime = timestamp;\n }\n\n const elapsed = timestamp - startTime;\n const progress = Math.min(elapsed / animationLength, 1);\n\n cstSegmentation.config.setSegmentSpecificConfig(\n toolGroupId,\n segmentationRepresentation.segmentationRepresentationUID,\n {\n [segmentIndex]: {\n LABELMAP: {\n fillAlpha: easeInOutBell(progress, fillAlpha),\n },\n },\n }\n );\n\n if (progress < 1) {\n requestAnimationFrame(animation);\n } else {\n cstSegmentation.config.setSegmentSpecificConfig(\n toolGroupId,\n segmentationRepresentation.segmentationRepresentationUID,\n {}\n );\n }\n };\n\n requestAnimationFrame(animation);\n }\n\n private _highlightContour(\n segmentIndex: number,\n alpha: number,\n hideOthers: boolean,\n segments: Segment[],\n toolGroupId: string,\n animationLength: number,\n segmentationRepresentation: cstTypes.ToolGroupSpecificRepresentation\n ) {\n const startTime = performance.now();\n\n const animate = (currentTime: number) => {\n const progress = (currentTime - startTime) / animationLength;\n if (progress >= 1) {\n cstSegmentation.config.setSegmentSpecificConfig(\n toolGroupId,\n segmentationRepresentation.segmentationRepresentationUID,\n {}\n );\n return;\n }\n\n const reversedProgress = reverseEaseInOutBell(progress, 0.1);\n cstSegmentation.config.setSegmentSpecificConfig(\n toolGroupId,\n segmentationRepresentation.segmentationRepresentationUID,\n {\n [segmentIndex]: {\n CONTOUR: {\n fillAlpha: reversedProgress,\n },\n },\n }\n );\n\n requestAnimationFrame(animate);\n };\n\n requestAnimationFrame(animate);\n }\n\n public removeSegmentationRepresentationFromToolGroup(\n toolGroupId: string,\n segmentationRepresentationUIDsIds?: string[]\n ): void {\n const uids = segmentationRepresentationUIDsIds || [];\n if (!uids.length) {\n const representations = cstSegmentation.state.getSegmentationRepresentations(toolGroupId);\n\n if (!representations || !representations.length) {\n return;\n }\n\n uids.push(...representations.map(rep => rep.segmentationRepresentationUID));\n }\n\n cstSegmentation.removeSegmentationsFromToolGroup(toolGroupId, uids);\n }\n\n /**\n * Removes a segmentation and broadcasts the removed event.\n *\n * @param {string} segmentationId The segmentation id\n */\n public remove(segmentationId: string): void {\n const segmentation = this.segmentations[segmentationId];\n const wasActive = segmentation.isActive;\n\n if (!segmentationId || !segmentation) {\n console.warn(`No segmentationId provided, or unable to find segmentation by id.`);\n return;\n }\n\n const { colorLUTIndex } = segmentation;\n this._removeSegmentationFromCornerstone(segmentationId);\n\n // Delete associated colormap\n // Todo: bring this back\n cstSegmentation.state.removeColorLUT(colorLUTIndex);\n\n delete this.segmentations[segmentationId];\n\n // If this segmentation was active, and there is another segmentation, set another one active.\n\n if (wasActive) {\n const remainingSegmentations = this._getSegmentations();\n\n const remainingHydratedSegmentations = remainingSegmentations.filter(\n segmentation => segmentation.hydrated\n );\n\n if (remainingHydratedSegmentations.length) {\n const { id } = remainingHydratedSegmentations[0];\n\n this._setActiveSegmentationForToolGroup(id, this._getApplicableToolGroupId(), false);\n }\n }\n\n this._setDisplaySetIsHydrated(segmentationId, false);\n\n this._broadcastEvent(this.EVENTS.SEGMENTATION_REMOVED, {\n segmentationId,\n });\n }\n\n public getConfiguration = (toolGroupId?: string): SegmentationConfig => {\n toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();\n\n const brushSize = 1;\n // const brushSize = cstUtils.segmentation.getBrushSizeForToolGroup(\n // toolGroupId\n // );\n\n const brushThresholdGate = 1;\n // const brushThresholdGate = cstUtils.segmentation.getBrushThresholdForToolGroup(\n // toolGroupId\n // );\n\n const segmentationRepresentations =\n this.getSegmentationRepresentationsForToolGroup(toolGroupId);\n\n const typeToUse = segmentationRepresentations?.[0]?.type || LABELMAP;\n\n const config = cstSegmentation.config.getGlobalConfig();\n const { renderInactiveSegmentations } = config;\n\n const representation = config.representations[typeToUse];\n\n const {\n renderOutline,\n outlineWidthActive,\n renderFill,\n fillAlpha,\n fillAlphaInactive,\n outlineOpacity,\n outlineOpacityInactive,\n } = representation;\n\n return {\n brushSize,\n brushThresholdGate,\n fillAlpha,\n fillAlphaInactive,\n outlineWidthActive,\n renderFill,\n renderInactiveSegmentations,\n renderOutline,\n outlineOpacity,\n outlineOpacityInactive,\n };\n };\n\n public setConfiguration = (configuration: SegmentationConfig): void => {\n const {\n brushSize,\n brushThresholdGate,\n fillAlpha,\n fillAlphaInactive,\n outlineWidthActive,\n outlineOpacity,\n renderFill,\n renderInactiveSegmentations,\n renderOutline,\n } = configuration;\n\n const setConfigValueIfDefined = (key, value, transformFn = null) => {\n if (value !== undefined) {\n const transformedValue = transformFn ? transformFn(value) : value;\n this._setSegmentationConfig(key, transformedValue);\n }\n };\n\n setConfigValueIfDefined('renderOutline', renderOutline);\n setConfigValueIfDefined('outlineWidthActive', outlineWidthActive);\n setConfigValueIfDefined('outlineOpacity', outlineOpacity, v => v / 100);\n setConfigValueIfDefined('fillAlpha', fillAlpha, v => v / 100);\n setConfigValueIfDefined('renderFill', renderFill);\n setConfigValueIfDefined('fillAlphaInactive', fillAlphaInactive, v => v / 100);\n setConfigValueIfDefined('outlineOpacityInactive', fillAlphaInactive, v =>\n Math.max(0.75, v / 100)\n );\n\n if (renderInactiveSegmentations !== undefined) {\n const config = cstSegmentation.config.getGlobalConfig();\n config.renderInactiveSegmentations = renderInactiveSegmentations;\n cstSegmentation.config.setGlobalConfig(config);\n }\n\n // if (brushSize !== undefined) {\n // const { toolGroupService } = this.servicesManager.services;\n\n // const toolGroupIds = toolGroupService.getToolGroupIds();\n\n // toolGroupIds.forEach(toolGroupId => {\n // cstUtils.segmentation.setBrushSizeForToolGroup(toolGroupId, brushSize);\n // });\n // }\n\n // if (brushThresholdGate !== undefined) {\n // const { toolGroupService } = this.servicesManager.services;\n\n // const toolGroupIds = toolGroupService.getFirstToolGroupIds();\n\n // toolGroupIds.forEach(toolGroupId => {\n // cstUtils.segmentation.setBrushThresholdForToolGroup(\n // toolGroupId,\n // brushThresholdGate\n // );\n // });\n // }\n\n this._broadcastEvent(this.EVENTS.SEGMENTATION_CONFIGURATION_CHANGED, this.getConfiguration());\n };\n\n public getLabelmapVolume = (segmentationId: string) => {\n return cache.getVolume(segmentationId);\n };\n\n public getSegmentationRepresentationsForToolGroup = toolGroupId => {\n return cstSegmentation.state.getSegmentationRepresentations(toolGroupId);\n };\n\n public setSegmentLabel(segmentationId: string, segmentIndex: number, label: string) {\n this._setSegmentLabel(segmentationId, segmentIndex, label);\n }\n\n private _setSegmentLabel(\n segmentationId: string,\n segmentIndex: number,\n label: string,\n suppressEvents = false\n ) {\n const segmentation = this.getSegmentation(segmentationId);\n\n if (segmentation === undefined) {\n throw new Error(`no segmentation for segmentationId: ${segmentationId}`);\n }\n\n const segmentInfo = segmentation.segments[segmentIndex];\n\n if (segmentInfo === undefined) {\n throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);\n }\n\n segmentInfo.label = label;\n\n if (suppressEvents === false) {\n // this._setSegmentationModified(segmentationId);\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n }\n }\n\n public shouldRenderSegmentation(viewportDisplaySetInstanceUIDs, segmentationFrameOfReferenceUID) {\n if (!viewportDisplaySetInstanceUIDs?.length) {\n return false;\n }\n\n const { displaySetService } = this.servicesManager.services;\n\n let shouldDisplaySeg = false;\n\n // check if the displaySet is sharing the same frameOfReferenceUID\n // with the new segmentation\n for (const displaySetInstanceUID of viewportDisplaySetInstanceUIDs) {\n const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);\n\n // Todo: this might not be ideal for use cases such as 4D, since we\n // don't want to show the segmentation for all the frames\n if (\n displaySet.isReconstructable &&\n displaySet?.images?.[0]?.FrameOfReferenceUID === segmentationFrameOfReferenceUID\n ) {\n shouldDisplaySeg = true;\n break;\n }\n }\n\n return shouldDisplaySeg;\n }\n\n private _getDefaultSegmentationScheme() {\n return {\n activeSegmentIndex: 1,\n cachedStats: {},\n label: '',\n segmentsLocked: [],\n displayText: [],\n hydrated: false, // by default we don't hydrate the segmentation for SEG displaySets\n segmentCount: 0,\n segments: [],\n isVisible: true,\n isActive: false,\n colorLUTIndex: 0,\n };\n }\n\n private _setActiveSegmentationForToolGroup(\n segmentationId: string,\n toolGroupId: string,\n suppressEvents = false\n ) {\n const segmentations = this._getSegmentations();\n const targetSegmentation = this.getSegmentation(segmentationId);\n\n if (targetSegmentation === undefined) {\n throw new Error(`no segmentation for segmentationId: ${segmentationId}`);\n }\n\n segmentations.forEach(segmentation => {\n segmentation.isActive = segmentation.id === segmentationId;\n });\n\n const representation = this._getSegmentationRepresentation(segmentationId, toolGroupId);\n\n cstSegmentation.activeSegmentation.setActiveSegmentationRepresentation(\n toolGroupId,\n representation.segmentationRepresentationUID\n );\n\n if (suppressEvents === false) {\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation: targetSegmentation,\n });\n }\n }\n\n private _toggleSegmentationVisibility = (segmentationId: string, suppressEvents = false) => {\n const segmentation = this.segmentations[segmentationId];\n\n if (!segmentation) {\n throw new Error(`Segmentation with segmentationId ${segmentationId} not found.`);\n }\n\n segmentation.isVisible = !segmentation.isVisible;\n\n this._updateCornerstoneSegmentationVisibility(segmentationId);\n\n if (suppressEvents === false) {\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n }\n };\n\n private _setActiveSegment(segmentationId: string, segmentIndex: number, suppressEvents = false) {\n const segmentation = this.getSegmentation(segmentationId);\n\n if (segmentation === undefined) {\n throw new Error(`no segmentation for segmentationId: ${segmentationId}`);\n }\n\n cstSegmentation.segmentIndex.setActiveSegmentIndex(segmentationId, segmentIndex);\n\n segmentation.activeSegmentIndex = segmentIndex;\n\n if (suppressEvents === false) {\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n }\n }\n\n private _getSegmentInfo(segmentation: Segmentation, segmentIndex: number) {\n const segments = segmentation.segments;\n\n if (!segments) {\n return;\n }\n\n if (segments && segments.length > 0) {\n return segments[segmentIndex];\n }\n }\n\n private _getVolumeIdForDisplaySet(displaySet) {\n const volumeLoaderSchema = displaySet.volumeLoaderSchema ?? VOLUME_LOADER_SCHEME;\n\n return `${volumeLoaderSchema}:${displaySet.displaySetInstanceUID}`;\n }\n\n private _setSegmentColor = (\n segmentationId: string,\n segmentIndex: number,\n color: ohifTypes.RGB,\n toolGroupId?: string,\n suppressEvents = false\n ) => {\n const segmentation = this.getSegmentation(segmentationId);\n\n if (segmentation === undefined) {\n throw new Error(`no segmentation for segmentationId: ${segmentationId}`);\n }\n\n const segmentInfo = this._getSegmentInfo(segmentation, segmentIndex);\n\n if (segmentInfo === undefined) {\n throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);\n }\n\n toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();\n\n const segmentationRepresentation = this._getSegmentationRepresentation(\n segmentationId,\n toolGroupId\n );\n\n if (!segmentationRepresentation) {\n throw new Error('Must add representation to toolgroup before setting segments');\n }\n const { segmentationRepresentationUID } = segmentationRepresentation;\n\n const rgbaColor = cstSegmentation.config.color.getColorForSegmentIndex(\n toolGroupId,\n segmentationRepresentationUID,\n segmentIndex\n );\n\n cstSegmentation.config.color.setColorForSegmentIndex(\n toolGroupId,\n segmentationRepresentationUID,\n segmentIndex,\n [...color, rgbaColor[3]]\n );\n\n segmentInfo.color = color;\n\n if (suppressEvents === false) {\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n }\n };\n\n private _getSegmentCenter(segmentationId, segmentIndex) {\n const segmentation = this.getSegmentation(segmentationId);\n\n if (!segmentation) {\n return;\n }\n\n const { cachedStats } = segmentation;\n\n if (!cachedStats) {\n return;\n }\n\n const { segmentCenter } = cachedStats;\n\n if (!segmentCenter) {\n return;\n }\n\n const { center } = segmentCenter[segmentIndex];\n\n return center;\n }\n\n private _setSegmentLocked(\n segmentationId: string,\n segmentIndex: number,\n isLocked: boolean,\n suppressEvents = false\n ) {\n const segmentation = this.getSegmentation(segmentationId);\n\n if (segmentation === undefined) {\n throw new Error(`no segmentation for segmentationId: ${segmentationId}`);\n }\n\n const segmentInfo = this._getSegmentInfo(segmentation, segmentIndex);\n\n if (segmentInfo === undefined) {\n throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);\n }\n\n segmentInfo.isLocked = isLocked;\n\n cstSegmentation.segmentLocking.setSegmentIndexLocked(segmentationId, segmentIndex, isLocked);\n\n if (suppressEvents === false) {\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n }\n }\n\n private _setSegmentVisibility(\n segmentationId: string,\n segmentIndex: number,\n isVisible: boolean,\n toolGroupId?: string,\n suppressEvents = false\n ) {\n toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();\n\n const { segmentationRepresentationUID, segmentation } = this._getSegmentationInfo(\n segmentationId,\n toolGroupId\n );\n\n if (segmentation === undefined) {\n throw new Error(`no segmentation for segmentationId: ${segmentationId}`);\n }\n\n const segmentInfo = this._getSegmentInfo(segmentation, segmentIndex);\n\n if (segmentInfo === undefined) {\n throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);\n }\n\n segmentInfo.isVisible = isVisible;\n\n cstSegmentation.config.visibility.setSegmentVisibility(\n toolGroupId,\n segmentationRepresentationUID,\n segmentIndex,\n isVisible\n );\n\n // make sure to update the isVisible flag on the segmentation\n // if a segment becomes invisible then the segmentation should be invisible\n // in the status as well, and show correct icon\n segmentation.isVisible = segmentation.segments\n .filter(Boolean)\n .every(segment => segment.isVisible);\n\n if (suppressEvents === false) {\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n }\n }\n\n private _setSegmentOpacity = (\n segmentationId: string,\n segmentIndex: number,\n opacity: number,\n toolGroupId?: string,\n suppressEvents = false\n ) => {\n const segmentation = this.getSegmentation(segmentationId);\n\n if (segmentation === undefined) {\n throw new Error(`no segmentation for segmentationId: ${segmentationId}`);\n }\n\n const segmentInfo = this._getSegmentInfo(segmentation, segmentIndex);\n\n if (segmentInfo === undefined) {\n throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);\n }\n\n toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();\n\n const segmentationRepresentation = this._getSegmentationRepresentation(\n segmentationId,\n toolGroupId\n );\n\n if (!segmentationRepresentation) {\n throw new Error('Must add representation to toolgroup before setting segments');\n }\n const { segmentationRepresentationUID } = segmentationRepresentation;\n\n const rgbaColor = cstSegmentation.config.color.getColorForSegmentIndex(\n toolGroupId,\n segmentationRepresentationUID,\n segmentIndex\n );\n\n cstSegmentation.config.color.setColorForSegmentIndex(\n toolGroupId,\n segmentationRepresentationUID,\n segmentIndex,\n [rgbaColor[0], rgbaColor[1], rgbaColor[2], opacity]\n );\n\n segmentInfo.opacity = opacity;\n\n if (suppressEvents === false) {\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n }\n };\n\n private _setSegmentLabel(\n segmentationId: string,\n segmentIndex: number,\n segmentLabel: string,\n suppressEvents = false\n ) {\n const segmentation = this.getSegmentation(segmentationId);\n\n if (segmentation === undefined) {\n throw new Error(`no segmentation for segmentationId: ${segmentationId}`);\n }\n\n const segmentInfo = this._getSegmentInfo(segmentation, segmentIndex);\n\n if (segmentInfo === undefined) {\n throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);\n }\n\n segmentInfo.label = segmentLabel;\n\n if (suppressEvents === false) {\n this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {\n segmentation,\n });\n }\n }\n\n private _getSegmentationRepresentation(segmentationId, toolGroupId) {\n const segmentationRepresentations =\n this.getSegmentationRepresentationsForToolGroup(toolGroupId);\n\n if (!segmentationRepresentations?.length) {\n return;\n }\n\n // Todo: this finds the first segmentation representation that matches the segmentationId\n // If there are two labelmap representations from the same segmentation, this will not work\n const representation = segmentationRepresentations.find(\n representation => representation.segmentationId === segmentationId\n );\n\n return representation;\n }\n\n private _setSegmentationConfig = (property, value) => {\n // Todo: currently we only support global config, and we get the type\n // from the first segmentation\n const typeToUse = this.getSegmentations()[0].type;\n\n const { cornerstoneViewportService } = this.servicesManager.services;\n\n const config = cstSegmentation.config.getGlobalConfig();\n\n config.representations[typeToUse][property] = value;\n\n // Todo: add non global (representation specific config as well)\n cstSegmentation.config.setGlobalConfig(config);\n\n const renderingEngine = cornerstoneViewportService.getRenderingEngine();\n const viewportIds = cornerstoneViewportService.getViewportIds();\n\n renderingEngine.renderViewports(viewportIds);\n };\n\n private _initSegmentationService() {\n // Connect Segmentation Service to Cornerstone3D.\n eventTarget.addEventListener(\n csToolsEnums.Events.SEGMENTATION_MODIFIED,\n this._onSegmentationModifiedFromSource\n );\n\n eventTarget.addEventListener(\n csToolsEnums.Events.SEGMENTATION_DATA_MODIFIED,\n this._onSegmentationDataModified\n );\n }\n\n private _onSegmentationDataModified = evt => {\n const { segmentationId } = evt.detail;\n\n const segmentation = this.getSegmentation(segmentationId);\n\n if (segmentation === undefined) {\n // Part of add operation, not update operation, exit early.\n return;\n }\n\n this._broadcastEvent(this.EVENTS.SEGMENTATION_DATA_MODIFIED, {\n segmentation,\n });\n };\n\n private _onSegmentationModifiedFromSource = evt => {\n const { segmentationId } = evt.detail;\n\n const segmentation = this.segmentations[segmentationId];\n\n if (segmentation === undefined) {\n // Part of add operation, not update operation, exit early.\n return;\n }\n\n const segmentationState = cstSegmentation.state.getSegmentation(segmentationId);\n\n if (!segmentationState) {\n return;\n }\n\n const { activeSegmentIndex, cachedStats, segmentsLocked, label, type } = segmentationState;\n\n if (![LABELMAP, CONTOUR].includes(type)) {\n throw new Error(\n `Unsupported segmentation type: ${type}. Only ${LABELMAP} and ${CONTOUR} are supported.`\n );\n }\n\n const representationData = segmentationState.representationData[type];\n\n // TODO: handle other representations when available in cornerstone3D\n const segmentationSchema = {\n ...segmentation,\n activeSegmentIndex,\n cachedStats,\n displayText: [],\n id: segmentationId,\n label,\n segmentsLocked,\n type,\n representationData: {\n [type]: {\n ...representationData,\n },\n },\n };\n\n try {\n this.addOrUpdateSegmentation(segmentationSchema);\n } catch (error) {\n console.warn(`Failed to add/update segmentation ${segmentationId}`, error);\n }\n };\n\n private _getSegmentationInfo(segmentationId: string, toolGroupId: string) {\n const segmentation = this.getSegmentation(segmentationId);\n\n if (segmentation === undefined) {\n throw new Error(`no segmentation for segmentationId: ${segmentationId}`);\n }\n const segmentationRepresentation = this._getSegmentationRepresentation(\n segmentationId,\n toolGroupId\n );\n\n if (!segmentationRepresentation) {\n throw new Error('Must add representation to toolgroup before setting segments');\n }\n\n const { segmentationRepresentationUID } = segmentationRepresentation;\n\n return { segmentationRepresentationUID, segmentation };\n }\n\n private _removeSegmentationFromCornerstone(segmentationId: string) {\n // TODO: This should be from the configuration\n const removeFromCache = true;\n const segmentationState = cstSegmentation.state;\n const sourceSegState = segmentationState.getSegmentation(segmentationId);\n\n if (!sourceSegState) {\n return;\n }\n\n const toolGroupIds = segmentationState.getToolGroupIdsWithSegmentation(segmentationId);\n\n toolGroupIds.forEach(toolGroupId => {\n const segmentationRepresentations =\n segmentationState.getSegmentationRepresentations(toolGroupId);\n\n const UIDsToRemove = [];\n segmentationRepresentations.forEach(representation => {\n if (representation.segmentationId === segmentationId) {\n UIDsToRemove.push(representation.segmentationRepresentationUID);\n }\n });\n\n // remove segmentation representations\n cstSegmentation.removeSegmentationsFromToolGroup(\n toolGroupId,\n UIDsToRemove,\n true // immediate\n );\n });\n\n // cleanup the segmentation state too\n segmentationState.removeSegmentation(segmentationId);\n\n if (removeFromCache && cache.getVolumeLoadObject(segmentationId)) {\n cache.removeVolumeLoadObject(segmentationId);\n }\n }\n\n private _updateCornerstoneSegmentations({ segmentationId, notYetUpdatedAtSource }) {\n if (notYetUpdatedAtSource === false) {\n return;\n }\n const segmentationState = cstSegmentation.state;\n const sourceSegmentation = segmentationState.getSegmentation(segmentationId);\n const segmentation = this.segmentations[segmentationId];\n const { label, cachedStats } = segmentation;\n\n // Update the label in the source if necessary\n if (sourceSegmentation.label !== label) {\n sourceSegmentation.label = label;\n }\n\n if (!isEqual(sourceSegmentation.cachedStats, cachedStats)) {\n sourceSegmentation.cachedStats = cachedStats;\n }\n }\n\n private _updateCornerstoneSegmentationVisibility = segmentationId => {\n const segmentationState = cstSegmentation.state;\n const toolGroupIds = segmentationState.getToolGroupIdsWithSegmentation(segmentationId);\n\n toolGroupIds.forEach(toolGroupId => {\n const segmentationRepresentations =\n cstSegmentation.state.getSegmentationRepresentations(toolGroupId);\n\n if (segmentationRepresentations.length === 0) {\n return;\n }\n\n // Todo: this finds the first segmentation representation that matches the segmentationId\n // If there are two labelmap representations from the same segmentation, this will not work\n const representation = segmentationRepresentations.find(\n representation => representation.segmentationId === segmentationId\n );\n\n const { segmentsHidden } = representation;\n\n const currentVisibility = segmentsHidden.size === 0 ? true : false;\n const newVisibility = !currentVisibility;\n\n cstSegmentation.config.visibility.setSegmentationVisibility(\n toolGroupId,\n representation.segmentationRepresentationUID,\n newVisibility\n );\n\n // update segments visibility\n const { segmentation } = this._getSegmentationInfo(segmentationId, toolGroupId);\n\n const segments = segmentation.segments.filter(Boolean);\n\n segments.forEach(segment => {\n segment.isVisible = newVisibility;\n });\n });\n };\n\n private _getToolGroupIdsWithSegmentation(segmentationId: string) {\n const segmentationState = cstSegmentation.state;\n const toolGroupIds = segmentationState.getToolGroupIdsWithSegmentation(segmentationId);\n\n return toolGroupIds;\n }\n\n private _getFrameOfReferenceUIDForSeg(displaySet) {\n const frameOfReferenceUID = displaySet.instance?.FrameOfReferenceUID;\n\n if (frameOfReferenceUID) {\n return frameOfReferenceUID;\n }\n\n // if not found we should try the ReferencedFrameOfReferenceSequence\n const referencedFrameOfReferenceSequence =\n displaySet.instance?.ReferencedFrameOfReferenceSequence;\n\n if (referencedFrameOfReferenceSequence) {\n return referencedFrameOfReferenceSequence.FrameOfReferenceUID;\n }\n }\n\n private _getApplicableToolGroupId = () => {\n const { toolGroupService, viewportGridService, cornerstoneViewportService } =\n this.servicesManager.services;\n\n const viewportInfo = cornerstoneViewportService.getViewportInfo(\n viewportGridService.getActiveViewportId()\n );\n\n if (!viewportInfo) {\n const toolGroupIds = toolGroupService.getToolGroupIds();\n\n return toolGroupIds[0];\n }\n\n return viewportInfo.getToolGroupId();\n };\n\n private getNextColorLUTIndex = (): number => {\n let i = 0;\n while (true) {\n if (cstSegmentation.state.getColorLUT(i) === undefined) {\n return i;\n }\n\n i++;\n }\n };\n\n private generateNewColorLUT() {\n const newColorLUT = cloneDeep(COLOR_LUT);\n\n return newColorLUT;\n }\n\n /**\n * Converts object of objects to array.\n *\n * @return {Array} Array of objects\n */\n private arrayOfObjects = obj => {\n return Object.entries(obj).map(e => ({ [e[0]]: e[1] }));\n };\n}\n\nexport default SegmentationService;\nexport { EVENTS, VALUE_TYPES };\n","/**\n * Maps a DICOM RT Struct ROI Contour to a RTStruct data that can be used\n * in Segmentation Service\n *\n * @param structureSet - A DICOM RT Struct ROI Contour\n * @param rtDisplaySetUID - A CornerstoneTools DisplaySet UID\n * @returns An array of object that includes data, id, segmentIndex, color\n * and geometry Id\n */\nexport function mapROIContoursToRTStructData(structureSet: unknown, rtDisplaySetUID: unknown) {\n return structureSet.ROIContours.map(({ contourPoints, ROINumber, ROIName, colorArray }) => {\n const data = contourPoints.map(({ points, ...rest }) => {\n const newPoints = points.map(({ x, y, z }) => {\n return [x, y, z];\n });\n\n return {\n ...rest,\n points: newPoints,\n };\n });\n\n const id = ROIName || ROINumber;\n\n return {\n data,\n id,\n segmentIndex: ROINumber,\n color: colorArray,\n geometryId: `${rtDisplaySetUID}:${id}:segmentIndex-${ROINumber}`,\n };\n });\n}\n","import SegmentationService from './SegmentationService';\n\nexport default SegmentationService;\n","import { Enums } from '@cornerstonejs/core';\n\nconst STACK = 'stack';\nconst VOLUME = 'volume';\nconst ORTHOGRAPHIC = 'orthographic';\nconst VOLUME_3D = 'volume3d';\n\nexport default function getCornerstoneViewportType(viewportType: string): Enums.ViewportType {\n const lowerViewportType = viewportType.toLowerCase();\n if (lowerViewportType === STACK) {\n return Enums.ViewportType.STACK;\n }\n\n if (lowerViewportType === VOLUME || lowerViewportType === ORTHOGRAPHIC) {\n return Enums.ViewportType.ORTHOGRAPHIC;\n }\n\n if (lowerViewportType === VOLUME_3D) {\n return Enums.ViewportType.VOLUME_3D;\n }\n\n throw new Error(`Invalid viewport type: ${viewportType}. Valid types are: stack, volume`);\n}\n","import { ServicesManager, Types } from '@ohif/core';\nimport { cache as cs3DCache, Enums, volumeLoader, utilities as utils } from '@cornerstonejs/core';\n\nimport getCornerstoneViewportType from '../../utils/getCornerstoneViewportType';\nimport { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';\n\nconst VOLUME_LOADER_SCHEME = 'cornerstoneStreamingImageVolume';\n\nclass CornerstoneCacheService {\n static REGISTRATION = {\n name: 'cornerstoneCacheService',\n altName: 'CornerstoneCacheService',\n create: ({ servicesManager }: Types.Extensions.ExtensionParams): CornerstoneCacheService => {\n return new CornerstoneCacheService(servicesManager);\n },\n };\n\n stackImageIds: Map = new Map();\n volumeImageIds: Map = new Map();\n readonly servicesManager: ServicesManager;\n\n constructor(servicesManager: ServicesManager) {\n this.servicesManager = servicesManager;\n }\n\n public getCacheSize() {\n return cs3DCache.getCacheSize();\n }\n\n public getCacheFreeSpace() {\n return cs3DCache.getBytesAvailable();\n }\n\n public async createViewportData(\n displaySets: unknown[],\n viewportOptions: Record,\n dataSource: unknown,\n initialImageIndex?: number\n ): Promise {\n let viewportType = viewportOptions.viewportType as string;\n\n // Todo: Since Cornerstone 3D currently doesn't support segmentation\n // on stack viewport, we should check if whether the the displaySets\n // that are about to be displayed are referenced in a segmentation\n // as a reference volume, if so, we should hang a volume viewport\n // instead of a stack viewport\n if (this._shouldRenderSegmentation(displaySets)) {\n viewportType = 'volume';\n\n // update viewportOptions to reflect the new viewport type\n viewportOptions.viewportType = viewportType;\n }\n\n const cs3DViewportType = getCornerstoneViewportType(viewportType);\n let viewportData: StackViewportData | VolumeViewportData;\n\n if (cs3DViewportType === Enums.ViewportType.STACK) {\n viewportData = await this._getStackViewportData(\n dataSource,\n displaySets,\n initialImageIndex,\n cs3DViewportType\n );\n }\n\n if (\n cs3DViewportType === Enums.ViewportType.ORTHOGRAPHIC ||\n cs3DViewportType === Enums.ViewportType.VOLUME_3D\n ) {\n viewportData = await this._getVolumeViewportData(dataSource, displaySets, cs3DViewportType);\n }\n\n viewportData.viewportType = cs3DViewportType;\n\n return viewportData;\n }\n\n public async invalidateViewportData(\n viewportData: VolumeViewportData,\n invalidatedDisplaySetInstanceUID: string,\n dataSource,\n displaySetService\n ) {\n if (viewportData.viewportType === Enums.ViewportType.STACK) {\n return this._getCornerstoneStackImageIds(\n displaySetService.getDisplaySetByUID(invalidatedDisplaySetInstanceUID),\n dataSource\n );\n }\n\n // Todo: grab the volume and get the id from the viewport itself\n const volumeId = `${VOLUME_LOADER_SCHEME}:${invalidatedDisplaySetInstanceUID}`;\n\n const volume = cs3DCache.getVolume(volumeId);\n\n if (volume) {\n cs3DCache.removeVolumeLoadObject(volumeId);\n this.volumeImageIds.delete(volumeId);\n }\n\n const displaySets = viewportData.data.map(({ displaySetInstanceUID }) =>\n displaySetService.getDisplaySetByUID(displaySetInstanceUID)\n );\n\n const newViewportData = await this._getVolumeViewportData(\n dataSource,\n displaySets,\n viewportData.viewportType\n );\n\n return newViewportData;\n }\n\n private _getStackViewportData(\n dataSource,\n displaySets,\n initialImageIndex,\n viewportType: Enums.ViewportType\n ): StackViewportData {\n // For Stack Viewport we don't have fusion currently\n const displaySet = displaySets[0];\n\n let stackImageIds = this.stackImageIds.get(displaySet.displaySetInstanceUID);\n\n if (!stackImageIds) {\n stackImageIds = this._getCornerstoneStackImageIds(displaySet, dataSource);\n this.stackImageIds.set(displaySet.displaySetInstanceUID, stackImageIds);\n }\n\n const { displaySetInstanceUID, StudyInstanceUID, isCompositeStack } = displaySet;\n\n const StackViewportData: StackViewportData = {\n viewportType,\n data: {\n StudyInstanceUID,\n displaySetInstanceUID,\n isCompositeStack,\n imageIds: stackImageIds,\n },\n };\n\n if (typeof initialImageIndex === 'number') {\n StackViewportData.data.initialImageIndex = initialImageIndex;\n }\n\n return StackViewportData;\n }\n\n private async _getVolumeViewportData(\n dataSource,\n displaySets,\n viewportType: Enums.ViewportType\n ): Promise {\n // Todo: Check the cache for multiple scenarios to see if we need to\n // decache the volume data from other viewports or not\n\n const volumeData = [];\n\n for (const displaySet of displaySets) {\n // Don't create volumes for the displaySets that have custom load\n // function (e.g., SEG, RT, since they rely on the reference volumes\n // and they take care of their own loading after they are created in their\n // getSOPClassHandler method\n\n if (displaySet.load && displaySet.load instanceof Function) {\n const { userAuthenticationService } = this.servicesManager.services;\n const headers = userAuthenticationService.getAuthorizationHeader();\n await displaySet.load({ headers });\n\n volumeData.push({\n studyInstanceUID: displaySet.StudyInstanceUID,\n displaySetInstanceUID: displaySet.displaySetInstanceUID,\n });\n\n // Todo: do some cache check and empty the cache if needed\n continue;\n }\n\n const volumeLoaderSchema = displaySet.volumeLoaderSchema ?? VOLUME_LOADER_SCHEME;\n\n const volumeId = `${volumeLoaderSchema}:${displaySet.displaySetInstanceUID}`;\n\n let volumeImageIds = this.volumeImageIds.get(displaySet.displaySetInstanceUID);\n\n let volume = cs3DCache.getVolume(volumeId);\n\n if (!volumeImageIds || !volume) {\n volumeImageIds = this._getCornerstoneVolumeImageIds(displaySet, dataSource);\n\n volume = await volumeLoader.createAndCacheVolume(volumeId, {\n imageIds: volumeImageIds,\n });\n\n this.volumeImageIds.set(displaySet.displaySetInstanceUID, volumeImageIds);\n }\n\n volumeData.push({\n StudyInstanceUID: displaySet.StudyInstanceUID,\n displaySetInstanceUID: displaySet.displaySetInstanceUID,\n volume,\n volumeId,\n imageIds: volumeImageIds,\n });\n }\n\n return {\n viewportType,\n data: volumeData,\n };\n }\n\n private _shouldRenderSegmentation(displaySets) {\n const { segmentationService, displaySetService } = this.servicesManager.services;\n\n const viewportDisplaySetInstanceUIDs = displaySets.map(\n ({ displaySetInstanceUID }) => displaySetInstanceUID\n );\n\n // check inside segmentations if any of them are referencing the displaySets\n // that are about to be displayed\n const segmentations = segmentationService.getSegmentations();\n\n for (const segmentation of segmentations) {\n const segDisplaySetInstanceUID = segmentation.displaySetInstanceUID;\n const segDisplaySet = displaySetService.getDisplaySetByUID(segDisplaySetInstanceUID);\n\n const instance = segDisplaySet.instances?.[0] || segDisplaySet.instance;\n\n const shouldDisplaySeg = segmentationService.shouldRenderSegmentation(\n viewportDisplaySetInstanceUIDs,\n instance.FrameOfReferenceUID\n );\n\n if (shouldDisplaySeg) {\n return true;\n }\n }\n }\n\n private _getCornerstoneStackImageIds(displaySet, dataSource): string[] {\n return dataSource.getImageIdsForDisplaySet(displaySet);\n }\n\n private _getCornerstoneVolumeImageIds(displaySet, dataSource): string[] {\n const stackImageIds = this._getCornerstoneStackImageIds(displaySet, dataSource);\n\n return stackImageIds;\n }\n}\n\nexport default CornerstoneCacheService;\n","import CornerstoneCacheService from './CornerstoneCacheService';\n\nexport default CornerstoneCacheService;\n","const RENDERING_ENGINE_ID = 'OHIFCornerstoneRenderingEngine';\n\nexport { RENDERING_ENGINE_ID };\n","import { Types, Enums } from '@cornerstonejs/core';\nimport { Types as UITypes } from '@ohif/ui';\nimport { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';\nimport getCornerstoneBlendMode from '../../utils/getCornerstoneBlendMode';\nimport getCornerstoneOrientation from '../../utils/getCornerstoneOrientation';\nimport getCornerstoneViewportType from '../../utils/getCornerstoneViewportType';\nimport JumpPresets from '../../utils/JumpPresets';\nimport { SyncGroup } from '../SyncGroupService/SyncGroupService';\n\nexport type InitialImageOptions = {\n index?: number;\n preset?: JumpPresets;\n};\n\nexport type ViewportOptions = {\n id?: string;\n viewportType: Enums.ViewportType;\n toolGroupId: string;\n viewportId: string;\n // Presentation ID to store/load presentation state from\n presentationIds?: UITypes.PresentationIds;\n orientation?: Enums.OrientationAxis;\n background?: Types.Point3;\n displayArea?: Types.DisplayArea;\n syncGroups?: SyncGroup[];\n initialImageOptions?: InitialImageOptions;\n customViewportProps?: Record;\n /*\n * Allows drag and drop of display sets not matching viewport options, but\n * doesn't show them initially. Displays initially blank if no required match\n */\n allowUnmatchedView?: boolean;\n};\n\nexport type PublicViewportOptions = {\n id?: string;\n viewportType?: string;\n toolGroupId?: string;\n presentationIds?: UITypes.PresentationIds;\n viewportId?: string;\n orientation?: Enums.OrientationAxis;\n background?: Types.Point3;\n displayArea?: Types.DisplayArea;\n syncGroups?: SyncGroup[];\n initialImageOptions?: InitialImageOptions;\n customViewportProps?: Record;\n allowUnmatchedView?: boolean;\n};\n\nexport type DisplaySetSelector = {\n id?: string;\n options?: PublicDisplaySetOptions;\n};\n\nexport type PublicDisplaySetOptions = {\n /** The display set options can have an id in order to distinguish\n * it from other similar items.\n */\n id?: string;\n voi?: VOI;\n voiInverted?: boolean;\n blendMode?: string;\n slabThickness?: number;\n colormap?: string;\n displayPreset?: string;\n};\n\nexport type DisplaySetOptions = {\n id?: string;\n voi?: VOI;\n voiInverted: boolean;\n blendMode?: Enums.BlendModes;\n slabThickness?: number;\n colormap?: string;\n displayPreset?: string;\n};\n\ntype VOI = {\n windowWidth: number;\n windowCenter: number;\n};\n\nexport type DisplaySet = {\n displaySetInstanceUID: string;\n};\n\nconst STACK = 'stack';\nconst DEFAULT_TOOLGROUP_ID = 'default';\n\n// Return true if the data contains the given display set UID OR the imageId\n// if it is a composite object.\nconst dataContains = (data, displaySetUID: string, imageId?: string): boolean => {\n if (data.displaySetInstanceUID === displaySetUID) {\n return true;\n }\n if (imageId && data.isCompositeStack && data.imageIds) {\n return !!data.imageIds.find(dataId => dataId === imageId);\n }\n return false;\n};\n\nclass ViewportInfo {\n private viewportId = '';\n private element: HTMLDivElement;\n private viewportOptions: ViewportOptions;\n private displaySetOptions: Array;\n private viewportData: StackViewportData | VolumeViewportData;\n private renderingEngineId: string;\n\n constructor(viewportId: string) {\n this.viewportId = viewportId;\n this.setPublicViewportOptions({});\n this.setPublicDisplaySetOptions([{}]);\n }\n\n /**\n * Return true if the viewport contains the given display set UID,\n * OR if it is a composite stack and contains the given imageId\n */\n public contains(displaySetUID: string, imageId: string): boolean {\n if (!this.viewportData?.data) {\n return false;\n }\n\n if (this.viewportData.data.length) {\n return !!this.viewportData.data.find(data => dataContains(data, displaySetUID, imageId));\n }\n return dataContains(this.viewportData.data, displaySetUID, imageId);\n }\n\n public destroy = (): void => {\n this.element = null;\n this.viewportData = null;\n this.viewportOptions = null;\n this.displaySetOptions = null;\n };\n\n public setRenderingEngineId(renderingEngineId: string): void {\n this.renderingEngineId = renderingEngineId;\n }\n\n public getRenderingEngineId(): string {\n return this.renderingEngineId;\n }\n\n public setViewportId(viewportId: string): void {\n this.viewportId = viewportId;\n }\n\n public setElement(element: HTMLDivElement): void {\n this.element = element;\n }\n\n public setViewportData(viewportData: StackViewportData | VolumeViewportData): void {\n this.viewportData = viewportData;\n }\n\n public getViewportData(): StackViewportData | VolumeViewportData {\n return this.viewportData;\n }\n\n public getElement(): HTMLDivElement {\n return this.element;\n }\n\n public getViewportId(): string {\n return this.viewportId;\n }\n\n public setPublicDisplaySetOptions(\n publicDisplaySetOptions: PublicDisplaySetOptions[] | DisplaySetSelector[]\n ): Array {\n // map the displaySetOptions and check if they are undefined then set them to default values\n const displaySetOptions = this.mapDisplaySetOptions(publicDisplaySetOptions);\n\n this.setDisplaySetOptions(displaySetOptions);\n\n return this.displaySetOptions;\n }\n\n public hasDisplaySet(displaySetInstanceUID: string): boolean {\n // Todo: currently this does not work for non image & referenceImage displaySets.\n // Since SEG and other derived displaySets are loaded in a different way, and not\n // via cornerstoneViewportService\n let viewportData = this.getViewportData();\n\n if (\n viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC ||\n viewportData.viewportType === Enums.ViewportType.VOLUME_3D\n ) {\n viewportData = viewportData as VolumeViewportData;\n return viewportData.data.some(\n ({ displaySetInstanceUID: dsUID }) => dsUID === displaySetInstanceUID\n );\n }\n\n viewportData = viewportData as StackViewportData;\n return viewportData.data.displaySetInstanceUID === displaySetInstanceUID;\n }\n\n public setPublicViewportOptions(viewportOptionsEntry: PublicViewportOptions): ViewportOptions {\n let viewportType = viewportOptionsEntry.viewportType;\n const { toolGroupId = DEFAULT_TOOLGROUP_ID, presentationIds } = viewportOptionsEntry;\n let orientation;\n\n if (!viewportType) {\n viewportType = getCornerstoneViewportType(STACK);\n } else {\n viewportType = getCornerstoneViewportType(viewportOptionsEntry.viewportType);\n }\n\n // map SAGITTAL, AXIAL, CORONAL orientation to be used by cornerstone\n if (viewportOptionsEntry.viewportType?.toLowerCase() !== STACK) {\n orientation = getCornerstoneOrientation(viewportOptionsEntry.orientation);\n }\n\n if (!toolGroupId) {\n toolGroupId = DEFAULT_TOOLGROUP_ID;\n }\n\n this.setViewportOptions({\n ...viewportOptionsEntry,\n viewportId: this.viewportId,\n viewportType: viewportType as Enums.ViewportType,\n orientation,\n toolGroupId,\n presentationIds,\n });\n\n return this.viewportOptions;\n }\n\n public setViewportOptions(viewportOptions: ViewportOptions): void {\n this.viewportOptions = viewportOptions;\n }\n\n public getViewportOptions(): ViewportOptions {\n return this.viewportOptions;\n }\n\n public setDisplaySetOptions(displaySetOptions: Array): void {\n this.displaySetOptions = displaySetOptions;\n }\n\n public getSyncGroups(): SyncGroup[] {\n this.viewportOptions.syncGroups ||= [];\n return this.viewportOptions.syncGroups;\n }\n\n public getDisplaySetOptions(): Array {\n return this.displaySetOptions;\n }\n\n public getViewportType(): Enums.ViewportType {\n return this.viewportOptions.viewportType || Enums.ViewportType.STACK;\n }\n\n public getToolGroupId(): string {\n return this.viewportOptions.toolGroupId;\n }\n\n public getBackground(): Types.Point3 {\n return this.viewportOptions.background || [0, 0, 0];\n }\n\n public getOrientation(): Enums.OrientationAxis {\n return this.viewportOptions.orientation;\n }\n\n public getDisplayArea(): Types.DisplayArea {\n return this.viewportOptions.displayArea;\n }\n\n public getInitialImageOptions(): InitialImageOptions {\n return this.viewportOptions.initialImageOptions;\n }\n\n // Handle incoming public display set options or a display set select\n // with a contained options.\n private mapDisplaySetOptions(\n options: PublicDisplaySetOptions[] | DisplaySetSelector[] = [{}]\n ): Array {\n const displaySetOptions: Array = [];\n\n options.forEach(item => {\n let option = item?.options || item;\n if (!option) {\n option = {\n blendMode: undefined,\n slabThickness: undefined,\n colormap: undefined,\n voi: {},\n voiInverted: false,\n };\n }\n const blendMode = getCornerstoneBlendMode(option.blendMode);\n\n displaySetOptions.push({\n voi: option.voi,\n voiInverted: option.voiInverted,\n colormap: option.colormap,\n slabThickness: option.slabThickness,\n blendMode,\n displayPreset: option.displayPreset,\n });\n });\n\n return displaySetOptions;\n }\n}\n\nexport default ViewportInfo;\n","import { Enums } from '@cornerstonejs/core';\n\nconst AXIAL = 'axial';\nconst SAGITTAL = 'sagittal';\nconst CORONAL = 'coronal';\n\nexport default function getCornerstoneOrientation(orientation: string): Enums.OrientationAxis {\n if (orientation) {\n switch (orientation.toLowerCase()) {\n case AXIAL:\n return Enums.OrientationAxis.AXIAL;\n case SAGITTAL:\n return Enums.OrientationAxis.SAGITTAL;\n case CORONAL:\n return Enums.OrientationAxis.CORONAL;\n default:\n return Enums.OrientationAxis.ACQUISITION;\n }\n }\n\n return Enums.OrientationAxis.ACQUISITION;\n}\n","import { Enums } from '@cornerstonejs/core';\n\nconst MIP = 'mip';\n\nexport default function getCornerstoneBlendMode(blendMode: string): Enums.BlendModes {\n if (!blendMode) {\n return Enums.BlendModes.COMPOSITE;\n }\n\n if (blendMode.toLowerCase() === MIP) {\n return Enums.BlendModes.MAXIMUM_INTENSITY_BLEND;\n }\n\n throw new Error();\n}\n","/**\n * Jump Presets - This enum defines the 3 jump states which are available\n * to be used with the jumpToSlice utility function.\n */\nenum JumpPresets {\n /** Jumps to first slice */\n First = 'first',\n /** Jumps to last slice */\n Last = 'last',\n /** Jumps to the middle slice */\n Middle = 'middle',\n}\n\nexport default JumpPresets;\n","import { PubSubService, ServicesManager } from '@ohif/core';\nimport * as OhifTypes from '@ohif/core/types';\nimport {\n RenderingEngine,\n StackViewport,\n Types,\n getRenderingEngine,\n utilities as csUtils,\n VolumeViewport,\n VolumeViewport3D,\n cache,\n Enums as csEnums,\n} from '@cornerstonejs/core';\n\nimport { utilities as csToolsUtils, Enums as csToolsEnums } from '@cornerstonejs/tools';\nimport { IViewportService } from './IViewportService';\nimport { RENDERING_ENGINE_ID } from './constants';\nimport ViewportInfo, { DisplaySetOptions, PublicViewportOptions } from './Viewport';\nimport { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';\nimport { Presentation, Presentations } from '../../types/Presentation';\n\nimport JumpPresets from '../../utils/JumpPresets';\n\nconst EVENTS = {\n VIEWPORT_DATA_CHANGED: 'event::cornerstoneViewportService:viewportDataChanged',\n};\n\n/**\n * Handles cornerstone viewport logic including enabling, disabling, and\n * updating the viewport.\n */\nclass CornerstoneViewportService extends PubSubService implements IViewportService {\n static REGISTRATION = {\n name: 'cornerstoneViewportService',\n altName: 'CornerstoneViewportService',\n create: ({\n servicesManager,\n }: OhifTypes.Extensions.ExtensionParams): CornerstoneViewportService => {\n return new CornerstoneViewportService(servicesManager);\n },\n };\n\n renderingEngine: Types.IRenderingEngine | null;\n viewportsById: Map = new Map();\n viewportGridResizeObserver: ResizeObserver | null;\n viewportsDisplaySets: Map = new Map();\n\n // Some configs\n enableResizeDetector: true;\n resizeRefreshRateMs: 200;\n resizeRefreshMode: 'debounce';\n servicesManager = null;\n\n constructor(servicesManager: ServicesManager) {\n super(EVENTS);\n this.renderingEngine = null;\n this.viewportGridResizeObserver = null;\n this.servicesManager = servicesManager;\n }\n\n /**\n * Adds the HTML element to the viewportService\n * @param {*} viewportId\n * @param {*} elementRef\n */\n public enableViewport(viewportId: string, elementRef: HTMLDivElement): void {\n const viewportInfo = new ViewportInfo(viewportId);\n viewportInfo.setElement(elementRef);\n this.viewportsById.set(viewportId, viewportInfo);\n }\n\n public getViewportIds(): string[] {\n return Array.from(this.viewportsById.keys());\n }\n\n /**\n * It retrieves the renderingEngine if it does exist, or creates one otherwise\n * @returns {RenderingEngine} rendering engine\n */\n public getRenderingEngine() {\n // get renderingEngine from cache if it exists\n const renderingEngine = getRenderingEngine(RENDERING_ENGINE_ID);\n\n if (renderingEngine) {\n this.renderingEngine = renderingEngine;\n return this.renderingEngine;\n }\n\n if (!renderingEngine || renderingEngine.hasBeenDestroyed) {\n this.renderingEngine = new RenderingEngine(RENDERING_ENGINE_ID);\n }\n\n return this.renderingEngine;\n }\n\n /**\n * It triggers the resize on the rendering engine.\n */\n public resize() {\n const immediate = true;\n const keepCamera = true;\n\n this.renderingEngine.resize(immediate, keepCamera);\n this.renderingEngine.render();\n }\n\n /**\n * Removes the viewport from cornerstone, and destroys the rendering engine\n */\n public destroy() {\n this._removeResizeObserver();\n this.viewportGridResizeObserver = null;\n try {\n this.renderingEngine?.destroy?.();\n } catch (e) {\n console.warn('Rendering engine not destroyed', e);\n }\n this.viewportsDisplaySets.clear();\n this.renderingEngine = null;\n cache.purgeCache();\n }\n\n /**\n * Disables the viewport inside the renderingEngine, if no viewport is left\n * it destroys the renderingEngine.\n *\n * This is called when the element goes away entirely - with new viewportId's\n * created for every new viewport, this will be called whenever the set of\n * viewports is changed, but NOT when the viewport position changes only.\n *\n * @param viewportId - The viewportId to disable\n */\n public disableElement(viewportId: string): void {\n this.renderingEngine?.disableElement(viewportId);\n\n // clean up\n this.viewportsById.delete(viewportId);\n this.viewportsDisplaySets.delete(viewportId);\n }\n\n public setPresentations(viewport, presentations?: Presentations): void {\n const properties = presentations?.lutPresentation?.properties;\n if (properties) {\n viewport.setProperties(properties);\n }\n const camera = presentations?.positionPresentation?.camera;\n if (camera) {\n viewport.setCamera(camera);\n }\n }\n\n public getPresentation(viewportId: string): Presentation {\n const viewportInfo = this.viewportsById.get(viewportId);\n if (!viewportInfo) {\n return;\n }\n const { viewportType, presentationIds } = viewportInfo.getViewportOptions();\n\n const csViewport = this.getCornerstoneViewport(viewportId);\n if (!csViewport) {\n return;\n }\n\n const properties = csViewport.getProperties();\n if (properties.isComputedVOI) {\n delete properties.voiRange;\n delete properties.VOILUTFunction;\n }\n const initialImageIndex = csViewport.getCurrentImageIdIndex();\n const camera = csViewport.getCamera();\n return {\n presentationIds,\n viewportType: !viewportType || viewportType === 'stack' ? 'stack' : 'volume',\n properties,\n initialImageIndex,\n camera,\n };\n }\n\n public storePresentation({ viewportId }) {\n const stateSyncService = this.servicesManager.services.stateSyncService;\n let presentation;\n try {\n presentation = this.getPresentation(viewportId);\n } catch (error) {\n console.warn(error);\n }\n\n if (!presentation || !presentation.presentationIds) {\n return;\n }\n const { lutPresentationStore, positionPresentationStore } = stateSyncService.getState();\n const { presentationIds } = presentation;\n const { lutPresentationId, positionPresentationId } = presentationIds || {};\n const storeState = {};\n if (lutPresentationId) {\n storeState.lutPresentationStore = {\n ...lutPresentationStore,\n [lutPresentationId]: presentation,\n };\n }\n if (positionPresentationId) {\n storeState.positionPresentationStore = {\n ...positionPresentationStore,\n [positionPresentationId]: presentation,\n };\n }\n stateSyncService.store(storeState);\n }\n\n /**\n * Sets the viewport data for a viewport.\n * @param viewportId - The ID of the viewport to set the data for.\n * @param viewportData - The viewport data to set.\n * @param publicViewportOptions - The public viewport options.\n * @param publicDisplaySetOptions - The public display set options.\n * @param presentations - The presentations to set.\n */\n public setViewportData(\n viewportId: string,\n viewportData: StackViewportData | VolumeViewportData,\n publicViewportOptions: PublicViewportOptions,\n publicDisplaySetOptions: DisplaySetOptions[],\n presentations?: Presentations\n ): void {\n const renderingEngine = this.getRenderingEngine();\n\n // This is the old viewportInfo, which may have old options but we might be\n // using its viewport (same viewportId as the new viewportInfo)\n const viewportInfo = this.viewportsById.get(viewportId);\n\n // We should store the presentation for the current viewport since we can't only\n // rely to store it WHEN the viewport is disabled since we might keep around the\n // same viewport/element and just change the viewportData for it (drag and drop etc.)\n // the disableElement storePresentation handle would not be called in this case\n // and we would lose the presentation.\n this.storePresentation({ viewportId: viewportInfo.getViewportId() });\n\n if (!viewportInfo) {\n throw new Error('element is not enabled for the given viewportId');\n }\n\n // override the viewportOptions and displaySetOptions with the public ones\n // since those are the newly set ones, we set them here so that it handles defaults\n const displaySetOptions = viewportInfo.setPublicDisplaySetOptions(publicDisplaySetOptions);\n const viewportOptions = viewportInfo.setPublicViewportOptions(publicViewportOptions);\n\n const element = viewportInfo.getElement();\n const type = viewportInfo.getViewportType();\n const background = viewportInfo.getBackground();\n const orientation = viewportInfo.getOrientation();\n const displayArea = viewportInfo.getDisplayArea();\n\n const viewportInput: Types.PublicViewportInput = {\n viewportId,\n element,\n type,\n defaultOptions: {\n background,\n orientation,\n displayArea,\n },\n };\n\n // Rendering Engine Id set should happen before enabling the element\n // since there are callbacks that depend on the renderingEngine id\n // Todo: however, this is a limitation which means that we can't change\n // the rendering engine id for a given viewport which might be a super edge\n // case\n viewportInfo.setRenderingEngineId(renderingEngine.id);\n\n // Todo: this is not optimal at all, we are re-enabling the already enabled\n // element which is not what we want. But enabledElement as part of the\n // renderingEngine is designed to be used like this. This will trigger\n // ENABLED_ELEMENT again and again, which will run onEnableElement callbacks\n renderingEngine.enableElement(viewportInput);\n\n viewportInfo.setViewportOptions(viewportOptions);\n viewportInfo.setDisplaySetOptions(displaySetOptions);\n viewportInfo.setViewportData(viewportData);\n viewportInfo.setViewportId(viewportId);\n\n this.viewportsById.set(viewportId, viewportInfo);\n\n const viewport = renderingEngine.getViewport(viewportId);\n this._setDisplaySets(viewport, viewportData, viewportInfo, presentations);\n\n // The broadcast event here ensures that listeners have a valid, up to date\n // viewport to access. Doing it too early can result in exceptions or\n // invalid data.\n this._broadcastEvent(this.EVENTS.VIEWPORT_DATA_CHANGED, {\n viewportData,\n viewportId,\n });\n }\n\n public getCornerstoneViewport(\n viewportId: string\n ): Types.IStackViewport | Types.IVolumeViewport | null {\n const viewportInfo = this.getViewportInfo(viewportId);\n\n if (!viewportInfo || !this.renderingEngine || this.renderingEngine.hasBeenDestroyed) {\n return null;\n }\n\n const viewport = this.renderingEngine.getViewport(viewportId);\n\n return viewport;\n }\n\n public getViewportInfo(viewportId: string): ViewportInfo {\n return this.viewportsById.get(viewportId);\n }\n\n _setStackViewport(\n viewport: Types.IStackViewport,\n viewportData: StackViewportData,\n viewportInfo: ViewportInfo,\n presentations: Presentations\n ): void {\n const displaySetOptions = viewportInfo.getDisplaySetOptions();\n\n const { imageIds, initialImageIndex, displaySetInstanceUID } = viewportData.data;\n\n this.viewportsDisplaySets.set(viewport.id, [displaySetInstanceUID]);\n\n let initialImageIndexToUse =\n presentations?.positionPresentation?.initialImageIndex ?? initialImageIndex;\n\n if (initialImageIndexToUse === undefined || initialImageIndexToUse === null) {\n initialImageIndexToUse = this._getInitialImageIndexForViewport(viewportInfo, imageIds) || 0;\n }\n\n const properties = { ...presentations.lutPresentation?.properties };\n if (!presentations.lutPresentation?.properties) {\n const { voi, voiInverted } = displaySetOptions[0];\n if (voi && (voi.windowWidth || voi.windowCenter)) {\n const { lower, upper } = csUtils.windowLevel.toLowHighRange(\n voi.windowWidth,\n voi.windowCenter\n );\n properties.voiRange = { lower, upper };\n }\n\n if (voiInverted !== undefined) {\n properties.invert = voiInverted;\n }\n }\n\n viewport.setStack(imageIds, initialImageIndexToUse).then(() => {\n viewport.setProperties({ ...properties });\n const camera = presentations.positionPresentation?.camera;\n if (camera) {\n viewport.setCamera(camera);\n }\n });\n }\n\n private _getInitialImageIndexForViewport(\n viewportInfo: ViewportInfo,\n imageIds?: string[]\n ): number {\n const initialImageOptions = viewportInfo.getInitialImageOptions();\n\n if (!initialImageOptions) {\n return;\n }\n\n const { index, preset } = initialImageOptions;\n const viewportType = viewportInfo.getViewportType();\n\n let numberOfSlices;\n if (viewportType === csEnums.ViewportType.STACK) {\n numberOfSlices = imageIds.length;\n } else if (viewportType === csEnums.ViewportType.ORTHOGRAPHIC) {\n const viewport = this.getCornerstoneViewport(viewportInfo.getViewportId());\n const imageSliceData = csUtils.getImageSliceDataForVolumeViewport(viewport);\n\n if (!imageSliceData) {\n return;\n }\n\n ({ numberOfSlices } = imageSliceData);\n } else {\n return;\n }\n\n return this._getInitialImageIndex(numberOfSlices, index, preset);\n }\n\n _getInitialImageIndex(numberOfSlices: number, imageIndex?: number, preset?: JumpPresets): number {\n const lastSliceIndex = numberOfSlices - 1;\n\n if (imageIndex !== undefined) {\n return csToolsUtils.clip(imageIndex, 0, lastSliceIndex);\n }\n\n if (preset === JumpPresets.First) {\n return 0;\n }\n\n if (preset === JumpPresets.Last) {\n return lastSliceIndex;\n }\n\n if (preset === JumpPresets.Middle) {\n // Note: this is a simple but yet very important formula.\n // since viewport reset works with the middle slice\n // if the below formula is not correct, on a viewport reset\n // it will jump to a different slice than the middle one which\n // was the initial slice, and we have some tools such as Crosshairs\n // which rely on a relative camera modifications and those will break.\n return lastSliceIndex % 2 === 0 ? lastSliceIndex / 2 : (lastSliceIndex + 1) / 2;\n }\n\n return 0;\n }\n\n async _setVolumeViewport(\n viewport: Types.IVolumeViewport,\n viewportData: VolumeViewportData,\n viewportInfo: ViewportInfo,\n presentations: Presentations\n ): Promise {\n // TODO: We need to overhaul the way data sources work so requests can be made\n // async. I think we should follow the image loader pattern which is async and\n // has a cache behind it.\n // The problem is that to set this volume, we need the metadata, but the request is\n // already in-flight, and the promise is not cached, so we have no way to wait for\n // it and know when it has fully arrived.\n // loadStudyMetadata(StudyInstanceUID) => Promise([instances for study])\n // loadSeriesMetadata(StudyInstanceUID, SeriesInstanceUID) => Promise([instances for series])\n // If you call loadStudyMetadata and it's not in the DicomMetadataStore cache, it should fire\n // a request through the data source?\n // (This call may or may not create sub-requests for series metadata)\n const volumeInputArray = [];\n const displaySetOptionsArray = viewportInfo.getDisplaySetOptions();\n const { hangingProtocolService } = this.servicesManager.services;\n\n const volumeToLoad = [];\n const displaySetInstanceUIDs = [];\n\n for (const [index, data] of viewportData.data.entries()) {\n const { volume, imageIds, displaySetInstanceUID } = data;\n\n displaySetInstanceUIDs.push(displaySetInstanceUID);\n\n if (!volume) {\n console.log('Volume display set not found');\n continue;\n }\n\n volumeToLoad.push(volume);\n\n const displaySetOptions = displaySetOptionsArray[index];\n const { volumeId } = volume;\n\n volumeInputArray.push({\n imageIds,\n volumeId,\n blendMode: displaySetOptions.blendMode,\n slabThickness: this._getSlabThickness(displaySetOptions, volumeId),\n });\n }\n\n this.viewportsDisplaySets.set(viewport.id, displaySetInstanceUIDs);\n\n if (hangingProtocolService.getShouldPerformCustomImageLoad()) {\n // delegate the volume loading to the hanging protocol service if it has a custom image load strategy\n return hangingProtocolService.runImageLoadStrategy({\n viewportId: viewport.id,\n volumeInputArray,\n });\n }\n\n volumeToLoad.forEach(volume => {\n if (!volume.loadStatus.loaded && !volume.loadStatus.loading) {\n volume.load();\n }\n });\n\n // This returns the async continuation only\n return this.setVolumesForViewport(viewport, volumeInputArray, presentations);\n }\n\n public async setVolumesForViewport(viewport, volumeInputArray, presentations) {\n const { displaySetService, toolGroupService } = this.servicesManager.services;\n\n const viewportInfo = this.getViewportInfo(viewport.id);\n const displaySetOptions = viewportInfo.getDisplaySetOptions();\n\n // Todo: use presentations states\n const volumesProperties = volumeInputArray.map((volumeInput, index) => {\n const { volumeId } = volumeInput;\n const displaySetOption = displaySetOptions[index];\n const { voi, voiInverted, colormap, displayPreset } = displaySetOption;\n const properties = {};\n\n if (voi && (voi.windowWidth || voi.windowCenter)) {\n const { lower, upper } = csUtils.windowLevel.toLowHighRange(\n voi.windowWidth,\n voi.windowCenter\n );\n properties.voiRange = { lower, upper };\n }\n\n if (voiInverted !== undefined) {\n properties.invert = voiInverted;\n }\n\n if (colormap !== undefined) {\n properties.colormap = colormap;\n }\n\n if (displayPreset !== undefined) {\n properties.preset = displayPreset;\n }\n\n return { properties, volumeId };\n });\n\n await viewport.setVolumes(volumeInputArray);\n volumesProperties.forEach(({ properties, volumeId }) => {\n viewport.setProperties(properties, volumeId);\n });\n\n this.setPresentations(viewport, presentations);\n\n // load any secondary displaySets\n const displaySetInstanceUIDs = this.viewportsDisplaySets.get(viewport.id);\n\n // can be SEG or RTSTRUCT for now\n const overlayDisplaySet = displaySetInstanceUIDs\n .map(displaySetService.getDisplaySetByUID)\n .find(displaySet => displaySet?.isOverlayDisplaySet);\n\n if (overlayDisplaySet) {\n this.addOverlayRepresentationForDisplaySet(overlayDisplaySet, viewport);\n } else {\n // If the displaySet is not a SEG displaySet we assume it is a primary displaySet\n // and we can look into hydrated segmentations to check if any of them are\n // associated with the primary displaySet\n\n // get segmentations only returns the hydrated segmentations\n this._addSegmentationRepresentationToToolGroupIfNecessary(displaySetInstanceUIDs, viewport);\n }\n\n const toolGroup = toolGroupService.getToolGroupForViewport(viewport.id);\n csToolsUtils.segmentation.triggerSegmentationRender(toolGroup.id);\n\n const imageIndex = this._getInitialImageIndexForViewport(viewportInfo);\n\n if (imageIndex !== undefined) {\n csToolsUtils.jumpToSlice(viewport.element, {\n imageIndex,\n });\n }\n\n viewport.render();\n }\n\n private _addSegmentationRepresentationToToolGroupIfNecessary(\n displaySetInstanceUIDs: string[],\n viewport: any\n ) {\n const { segmentationService, toolGroupService } = this.servicesManager.services;\n\n const toolGroup = toolGroupService.getToolGroupForViewport(viewport.id);\n\n // this only returns hydrated segmentations\n const segmentations = segmentationService.getSegmentations();\n\n for (const segmentation of segmentations) {\n const toolGroupSegmentationRepresentations =\n segmentationService.getSegmentationRepresentationsForToolGroup(toolGroup.id) || [];\n\n // if there is already a segmentation representation for this segmentation\n // for this toolGroup, don't bother at all\n const isSegmentationInToolGroup = toolGroupSegmentationRepresentations.find(\n representation => representation.segmentationId === segmentation.id\n );\n\n if (isSegmentationInToolGroup) {\n continue;\n }\n\n // otherwise, check if the hydrated segmentations are in the same FrameOfReferenceUID\n // as the primary displaySet, if so add the representation (since it was not there)\n const { id: segDisplaySetInstanceUID } = segmentation;\n let segFrameOfReferenceUID = this._getFrameOfReferenceUID(segDisplaySetInstanceUID);\n\n if (!segFrameOfReferenceUID) {\n // if the segmentation displaySet does not have a FrameOfReferenceUID, we might check the\n // segmentation itself maybe it has a FrameOfReferenceUID\n const { FrameOfReferenceUID } = segmentation;\n if (FrameOfReferenceUID) {\n segFrameOfReferenceUID = FrameOfReferenceUID;\n }\n }\n\n if (!segFrameOfReferenceUID) {\n return;\n }\n\n let shouldDisplaySeg = false;\n\n for (const displaySetInstanceUID of displaySetInstanceUIDs) {\n const primaryFrameOfReferenceUID = this._getFrameOfReferenceUID(displaySetInstanceUID);\n\n if (segFrameOfReferenceUID === primaryFrameOfReferenceUID) {\n shouldDisplaySeg = true;\n break;\n }\n }\n\n if (!shouldDisplaySeg) {\n return;\n }\n\n segmentationService.addSegmentationRepresentationToToolGroup(\n toolGroup.id,\n segmentation.id,\n false, // already hydrated,\n segmentation.type\n );\n }\n }\n\n private addOverlayRepresentationForDisplaySet(displaySet: any, viewport: any) {\n const { segmentationService, toolGroupService } = this.servicesManager.services;\n\n const { referencedVolumeId } = displaySet;\n const segmentationId = displaySet.displaySetInstanceUID;\n\n const toolGroup = toolGroupService.getToolGroupForViewport(viewport.id);\n\n const representationType =\n referencedVolumeId && cache.getVolume(referencedVolumeId) !== undefined\n ? csToolsEnums.SegmentationRepresentations.Labelmap\n : csToolsEnums.SegmentationRepresentations.Contour;\n\n segmentationService.addSegmentationRepresentationToToolGroup(\n toolGroup.id,\n segmentationId,\n false,\n representationType\n );\n }\n\n // Todo: keepCamera is an interim solution until we have a better solution for\n // keeping the camera position when the viewport data is changed\n public updateViewport(viewportId: string, viewportData, keepCamera = false) {\n const viewportInfo = this.getViewportInfo(viewportId);\n const viewport = this.getCornerstoneViewport(viewportId);\n const viewportCamera = viewport.getCamera();\n\n if (viewport instanceof VolumeViewport || viewport instanceof VolumeViewport3D) {\n this._setVolumeViewport(viewport, viewportData, viewportInfo).then(() => {\n if (keepCamera) {\n viewport.setCamera(viewportCamera);\n viewport.render();\n }\n });\n\n return;\n }\n\n if (viewport instanceof StackViewport) {\n this._setStackViewport(viewport, viewportData, viewportInfo);\n return;\n }\n }\n\n _setDisplaySets(\n viewport: StackViewport | VolumeViewport,\n viewportData: StackViewportData | VolumeViewportData,\n viewportInfo: ViewportInfo,\n presentations: Presentations = {}\n ): void {\n if (viewport instanceof StackViewport) {\n this._setStackViewport(\n viewport,\n viewportData as StackViewportData,\n viewportInfo,\n presentations\n );\n } else if (viewport instanceof VolumeViewport || viewport instanceof VolumeViewport3D) {\n this._setVolumeViewport(\n viewport,\n viewportData as VolumeViewportData,\n viewportInfo,\n presentations\n );\n } else {\n throw new Error('Unknown viewport type');\n }\n }\n\n /**\n * Removes the resize observer from the viewport element\n */\n _removeResizeObserver() {\n if (this.viewportGridResizeObserver) {\n this.viewportGridResizeObserver.disconnect();\n }\n }\n\n _getSlabThickness(displaySetOptions, volumeId) {\n const { blendMode } = displaySetOptions;\n if (blendMode === undefined || displaySetOptions.slabThickness === undefined) {\n return;\n }\n\n // if there is a slabThickness set as a number then use it\n if (typeof displaySetOptions.slabThickness === 'number') {\n return displaySetOptions.slabThickness;\n }\n\n if (displaySetOptions.slabThickness.toLowerCase() === 'fullvolume') {\n // calculate the slab thickness based on the volume dimensions\n const imageVolume = cache.getVolume(volumeId);\n\n const { dimensions } = imageVolume;\n const slabThickness = Math.sqrt(\n dimensions[0] * dimensions[0] +\n dimensions[1] * dimensions[1] +\n dimensions[2] * dimensions[2]\n );\n\n return slabThickness;\n }\n }\n\n _getFrameOfReferenceUID(displaySetInstanceUID) {\n const { displaySetService } = this.servicesManager.services;\n const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);\n\n if (!displaySet) {\n return;\n }\n\n if (displaySet.frameOfReferenceUID) {\n return displaySet.frameOfReferenceUID;\n }\n\n if (displaySet.Modality === 'SEG') {\n const { instance } = displaySet;\n return instance.FrameOfReferenceUID;\n }\n\n if (displaySet.Modality === 'RTSTRUCT') {\n const { instance } = displaySet;\n return instance.ReferencedFrameOfReferenceSequence.FrameOfReferenceUID;\n }\n\n const { images } = displaySet;\n if (images && images.length) {\n return images[0].FrameOfReferenceUID;\n }\n }\n\n /**\n * Looks through the viewports to see if the specified measurement can be\n * displayed in one of the viewports.\n *\n * @param measurement\n * The measurement that is desired to view.\n * @param activeViewportId - the index that was active at the time the jump\n * was initiated.\n * @return the viewportId that the measurement should be displayed in.\n */\n public getViewportIdToJump(\n activeViewportId: string,\n displaySetInstanceUID: string,\n cameraProps: unknown\n ): string {\n const viewportInfo = this.getViewportInfo(activeViewportId);\n const { referencedImageId } = cameraProps;\n if (viewportInfo?.contains(displaySetInstanceUID, referencedImageId)) {\n return activeViewportId;\n }\n\n return (\n [...this.viewportsById.values()].find(viewportInfo =>\n viewportInfo.contains(displaySetInstanceUID, referencedImageId)\n )?.viewportId ?? null\n );\n }\n}\n\nexport default CornerstoneViewportService;\n","import { imageLoader } from '@cornerstonejs/core';\nimport dicomImageLoader from '@cornerstonejs/dicom-image-loader';\nimport { api } from 'dicomweb-client';\nimport { DICOMWeb, errorHandler } from '@ohif/core';\n\nconst getImageId = imageObj => {\n if (!imageObj) {\n return;\n }\n\n return typeof imageObj.getImageId === 'function' ? imageObj.getImageId() : imageObj.url;\n};\n\nconst findImageIdOnStudies = (studies, displaySetInstanceUID) => {\n const study = studies.find(study => {\n const displaySet = study.displaySets.some(\n displaySet => displaySet.displaySetInstanceUID === displaySetInstanceUID\n );\n return displaySet;\n });\n const { series = [] } = study;\n const { instances = [] } = series[0] || {};\n const instance = instances[0];\n\n return getImageId(instance);\n};\n\nconst someInvalidStrings = strings => {\n const stringsArray = Array.isArray(strings) ? strings : [strings];\n const emptyString = string => !string;\n let invalid = stringsArray.some(emptyString);\n return invalid;\n};\n\nconst getImageInstance = dataset => {\n return dataset && dataset.images && dataset.images[0];\n};\n\nconst getNonImageInstance = dataset => {\n return dataset && dataset.instance;\n};\n\nconst getImageInstanceId = imageInstance => {\n return getImageId(imageInstance);\n};\n\nconst fetchIt = (url, headers = DICOMWeb.getAuthorizationHeader()) => {\n return fetch(url, headers).then(response => response.arrayBuffer());\n};\n\nconst cornerstoneRetriever = imageId => {\n return imageLoader.loadAndCacheImage(imageId).then(image => {\n return image && image.data && image.data.byteArray.buffer;\n });\n};\n\nconst wadorsRetriever = (\n url,\n studyInstanceUID,\n seriesInstanceUID,\n sopInstanceUID,\n headers = DICOMWeb.getAuthorizationHeader(),\n errorInterceptor = errorHandler.getHTTPErrorHandler()\n) => {\n const config = {\n url,\n headers,\n errorInterceptor,\n };\n const dicomWeb = new api.DICOMwebClient(config);\n\n return dicomWeb.retrieveInstance({\n studyInstanceUID,\n seriesInstanceUID,\n sopInstanceUID,\n });\n};\n\nconst getImageLoaderType = imageId => {\n const loaderRegExp = /^\\w+\\:/;\n const loaderType = loaderRegExp.exec(imageId);\n\n return (\n (loaderRegExp.lastIndex === 0 &&\n loaderType &&\n loaderType[0] &&\n loaderType[0].replace(':', '')) ||\n ''\n );\n};\n\nclass DicomLoaderService {\n getLocalData(dataset, studies) {\n // Use referenced imageInstance\n const imageInstance = getImageInstance(dataset);\n const nonImageInstance = getNonImageInstance(dataset);\n\n if (\n (!imageInstance && !nonImageInstance) ||\n !nonImageInstance.imageId?.startsWith('dicomfile')\n ) {\n return;\n }\n\n const instance = imageInstance || nonImageInstance;\n\n let imageId = getImageInstanceId(instance);\n\n // or Try to get it from studies\n if (someInvalidStrings(imageId)) {\n imageId = findImageIdOnStudies(studies, dataset.displaySetInstanceUID);\n }\n\n if (!someInvalidStrings(imageId)) {\n return dicomImageLoader.wadouri.loadFileRequest(imageId);\n }\n }\n\n getDataByImageType(dataset) {\n const imageInstance = getImageInstance(dataset);\n\n if (imageInstance) {\n const imageId = getImageInstanceId(imageInstance);\n let getDicomDataMethod = fetchIt;\n const loaderType = getImageLoaderType(imageId);\n\n switch (loaderType) {\n case 'dicomfile':\n getDicomDataMethod = cornerstoneRetriever.bind(this, imageId);\n break;\n case 'wadors':\n const url = imageInstance.getData().wadoRoot;\n const studyInstanceUID = imageInstance.getStudyInstanceUID();\n const seriesInstanceUID = imageInstance.getSeriesInstanceUID();\n const sopInstanceUID = imageInstance.getSOPInstanceUID();\n const invalidParams = someInvalidStrings([\n url,\n studyInstanceUID,\n seriesInstanceUID,\n sopInstanceUID,\n ]);\n if (invalidParams) {\n return;\n }\n\n getDicomDataMethod = wadorsRetriever.bind(\n this,\n url,\n studyInstanceUID,\n seriesInstanceUID,\n sopInstanceUID\n );\n break;\n case 'wadouri':\n // Strip out the image loader specifier\n imageId = imageId.substring(imageId.indexOf(':') + 1);\n\n if (someInvalidStrings(imageId)) {\n return;\n }\n getDicomDataMethod = fetchIt.bind(this, imageId);\n break;\n default:\n throw new Error(`Unsupported image type: ${loaderType} for imageId: ${imageId}`);\n }\n\n return getDicomDataMethod();\n }\n }\n\n getDataByDatasetType(dataset) {\n const {\n StudyInstanceUID,\n SeriesInstanceUID,\n SOPInstanceUID,\n authorizationHeaders,\n wadoRoot,\n wadoUri,\n } = dataset;\n // Retrieve wadors or just try to fetch wadouri\n if (!someInvalidStrings(wadoRoot)) {\n return wadorsRetriever(\n wadoRoot,\n StudyInstanceUID,\n SeriesInstanceUID,\n SOPInstanceUID,\n authorizationHeaders\n );\n } else if (!someInvalidStrings(wadoUri)) {\n return fetchIt(wadoUri, { headers: authorizationHeaders });\n }\n }\n\n *getLoaderIterator(dataset, studies, headers) {\n yield this.getLocalData(dataset, studies);\n yield this.getDataByImageType(dataset);\n yield this.getDataByDatasetType(dataset);\n }\n\n findDicomDataPromise(dataset, studies, headers) {\n dataset.authorizationHeaders = headers;\n const loaderIterator = this.getLoaderIterator(dataset, studies);\n // it returns first valid retriever method.\n for (const loader of loaderIterator) {\n if (loader) {\n return loader;\n }\n }\n\n // in case of no valid loader\n throw new Error('Invalid dicom data loader');\n }\n}\n\nconst dicomLoaderService = new DicomLoaderService();\n\nexport default dicomLoaderService;\n","import packageJson from '../package.json';\n\nconst id = packageJson.name;\n\nexport { id };\n","import React from 'react';\nimport * as cornerstone from '@cornerstonejs/core';\nimport * as cornerstoneTools from '@cornerstonejs/tools';\nimport {\n Enums as cs3DEnums,\n imageLoadPoolManager,\n imageRetrievalPoolManager,\n} from '@cornerstonejs/core';\nimport { Enums as cs3DToolsEnums } from '@cornerstonejs/tools';\nimport { ServicesManager, Types } from '@ohif/core';\n\nimport init from './init';\nimport getCustomizationModule from './getCustomizationModule';\nimport getCommandsModule from './commandsModule';\nimport getHangingProtocolModule from './getHangingProtocolModule';\nimport ToolGroupService from './services/ToolGroupService';\nimport SyncGroupService from './services/SyncGroupService';\nimport SegmentationService from './services/SegmentationService';\nimport CornerstoneCacheService from './services/CornerstoneCacheService';\nimport CornerstoneViewportService from './services/ViewportService/CornerstoneViewportService';\nimport * as CornerstoneExtensionTypes from './types';\n\nimport { toolNames } from './initCornerstoneTools';\nimport { getEnabledElement, reset as enabledElementReset } from './state';\nimport dicomLoaderService from './utils/dicomLoaderService';\nimport getActiveViewportEnabledElement from './utils/getActiveViewportEnabledElement';\n\nimport { id } from './id';\nimport * as csWADOImageLoader from './initWADOImageLoader.js';\nimport { measurementMappingUtils } from './utils/measurementServiceMappings';\nimport type { PublicViewportOptions } from './services/ViewportService/Viewport';\n\nconst Component = React.lazy(() => {\n return import(/* webpackPrefetch: true */ './Viewport/OHIFCornerstoneViewport');\n});\n\nconst OHIFCornerstoneViewport = props => {\n return (\n Loading...}>\n \n \n );\n};\n\n/**\n *\n */\nconst cornerstoneExtension: Types.Extensions.Extension = {\n /**\n * Only required property. Should be a unique value across all extensions.\n */\n id,\n\n onModeExit: (): void => {\n // Empty out the image load and retrieval pools to prevent memory leaks\n // on the mode exits\n Object.values(cs3DEnums.RequestType).forEach(type => {\n imageLoadPoolManager.clearRequestStack(type);\n imageRetrievalPoolManager.clearRequestStack(type);\n });\n\n enabledElementReset();\n },\n\n /**\n * Register the Cornerstone 3D services and set them up for use.\n *\n * @param configuration.csToolsConfig - Passed directly to `initCornerstoneTools`\n */\n preRegistration: function (props: Types.Extensions.ExtensionParams): Promise {\n const { servicesManager } = props;\n servicesManager.registerService(CornerstoneViewportService.REGISTRATION);\n servicesManager.registerService(ToolGroupService.REGISTRATION);\n servicesManager.registerService(SyncGroupService.REGISTRATION);\n servicesManager.registerService(SegmentationService.REGISTRATION);\n servicesManager.registerService(CornerstoneCacheService.REGISTRATION);\n\n return init.call(this, props);\n },\n\n getHangingProtocolModule,\n getViewportModule({ servicesManager, commandsManager }) {\n const ExtendedOHIFCornerstoneViewport = props => {\n // const onNewImageHandler = jumpData => {\n // commandsManager.runCommand('jumpToImage', jumpData);\n // };\n const { toolbarService } = (servicesManager as ServicesManager).services;\n\n return (\n \n );\n };\n\n return [\n {\n name: 'cornerstone',\n component: ExtendedOHIFCornerstoneViewport,\n },\n ];\n },\n getCommandsModule,\n getCustomizationModule,\n getUtilityModule({ servicesManager }) {\n return [\n {\n name: 'common',\n exports: {\n getCornerstoneLibraries: () => {\n return { cornerstone, cornerstoneTools };\n },\n getEnabledElement,\n dicomLoaderService,\n },\n },\n {\n name: 'core',\n exports: {\n Enums: cs3DEnums,\n },\n },\n {\n name: 'tools',\n exports: {\n toolNames,\n Enums: cs3DToolsEnums,\n },\n },\n ];\n },\n};\n\nexport type { PublicViewportOptions };\nexport {\n measurementMappingUtils,\n CornerstoneExtensionTypes as Types,\n toolNames,\n getActiveViewportEnabledElement,\n};\nexport default cornerstoneExtension;\n","const state = {\n // The `defaultContext` of an extension's commandsModule\n DEFAULT_CONTEXT: 'CORNERSTONE',\n enabledElements: {},\n};\n\n/**\n * Sets the enabled element `dom` reference for an active viewport.\n * @param {HTMLElement} dom Active viewport element.\n * @return void\n */\nconst setEnabledElement = (viewportId: string, element: HTMLElement, context?: string): void => {\n const targetContext = context || state.DEFAULT_CONTEXT;\n\n state.enabledElements[viewportId] = {\n element,\n context: targetContext,\n };\n};\n\n/**\n * Grabs the enabled element `dom` reference of an active viewport.\n *\n * @return {HTMLElement} Active viewport element.\n */\nconst getEnabledElement = viewportId => {\n return state.enabledElements[viewportId];\n};\n\nconst reset = () => {\n state.enabledElements = {};\n};\n\nexport { setEnabledElement, getEnabledElement, reset };\n","import * as cornerstone from '@cornerstonejs/core';\n\n/**\n * It checks if the imageId is provided then it uses it to query\n * the metadata and get the SOPInstanceUID, SeriesInstanceUID and StudyInstanceUID.\n * If the imageId is not provided then undefined is returned.\n * @param {string} imageId The image id of the referenced image\n * @returns\n */\nexport default function getSOPInstanceAttributes(imageId) {\n if (imageId) {\n return _getUIDFromImageID(imageId);\n }\n\n // Todo: implement for volume viewports and use the referencedSeriesInstanceUID\n}\n\nfunction _getUIDFromImageID(imageId) {\n const instance = cornerstone.metaData.get('instance', imageId);\n\n return {\n SOPInstanceUID: instance.SOPInstanceUID,\n SeriesInstanceUID: instance.SeriesInstanceUID,\n StudyInstanceUID: instance.StudyInstanceUID,\n frameNumber: instance.frameNumber || 1,\n };\n}\n"],"names":["registerVolumeLoader","volumeLoader","initialized","initWADOImageLoader","userAuthenticationService","appConfig","extensionManager","dicomImageLoader","cornerstone","dicomParser","cornerstoneStreamingImageVolumeLoader","decodeConfig","convertFloatPixelDataToInt","use16BitDataType","Boolean","beforeSend","xhr","getActiveDataSource","getConfig","headers","getAuthorizationHeader","xhrRequestHeaders","Accept","Object","assign","errorInterceptor","error","errorHandler","getHTTPErrorHandler","config","maxWebWorkers","Math","min","max","navigator","hardwareConcurrency","maxNumberOfWebWorkers","startWebWorkersOnDemand","taskConfiguration","decodeTask","initializeCodecsOnStartup","usePDFJS","strict","initialize","initWebWorkers","uiDialogService","data","callback","dialogConfig","arguments","length","undefined","dialogId","label","text","dialogTitle","inputLabel","validateFunc","value","onSubmitHandler","_ref","action","id","dismiss","create","centralize","isDraggable","showOverlay","content","Dialog","contentProps","title","noCloseButton","onClose","actions","type","ButtonEnums","secondary","primary","onSubmit","body","_ref2","setValue","React","Input","autoFocus","className","labelClassName","onChange","event","persist","target","onKeyPress","key","getActiveViewportEnabledElement","viewportGridService","activeViewportId","getState","element","OHIFgetEnabledElement","getEnabledElement","calibrateImageSpacing","utilities","CalibrationLineTool","LengthTool","constructor","_renderingViewport","_lengthToolRenderAnnotation","this","renderAnnotation","enabledElement","svgDrawingHelper","viewport","_getTextLines","targetId","canvasPoint1","canvasPoint2","handles","points","map","p","worldToCanvas","round","point1","point2","dx","dy","sqrt","calculateLength2","toolName","onCompletedCalibrationLine","servicesManager","csToolsEvent","services","annotationAddedEventDetail","detail","annotation","metadata","annotationData","referencedImageId","imageId","pos1","pos2","dz","calculateLength3","metaData","calibratedPixelSpacing","imagePlaneModule","rowPixelSpacing","columnPixelSpacing","Promise","resolve","reject","callInputDialog","newLength","spacingScale","getRenderingEngine","scale","adjustCalibration","Number","parseFloat","val","v","isNaN","ImageOverlayViewerTool","AnnotationDisplayTool","super","supportedInteractionTypes","configuration","fillColor","_cachedOverlayMetadata","Map","_cachedStats","onSetToolDisabled","getReferencedImageId","overlays","get","set","_getCachedStat","then","cachedStat","forEach","overlay","_renderOverlay","VolumeViewport","getTargetId","split","overlayData","_id","columns","width","rows","height","x","y","overlayTopLeftWorldPos","overlayTopLeftOnCanvas","overlayBottomRightWorldPos","overlayBottomRightOnCanvas","svgNodeHash","existingImageElement","getSvgNode","attributes","href","dataUrl","console","warn","drawing","setNodeTouched","newImageElement","document","createElementNS","appendNode","overlayMetadata","color","_isSameColor","all","filter","pixelData","async","idx","Value","Array","retrieveBulkData","_renderOverlayToDataUrl","guid","color1","color2","pixelDataRaw","pixelDataView","DataView","totalBits","canvas","createElement","ctx","getContext","clearRect","globalCompositeOperation","imageData","getImageData","i","bitIdx","byteIdx","getUint8","putImageData","toDataURL","toolNames","Pan","PanTool","ArrowAnnotate","ArrowAnnotateTool","WindowLevel","WindowLevelTool","StackScroll","StackScrollTool","StackScrollMouseWheel","StackScrollMouseWheelTool","Zoom","ZoomTool","VolumeRotateMouseWheel","VolumeRotateMouseWheelTool","MipJumpToClick","MIPJumpToClickTool","Length","DragProbe","DragProbeTool","Probe","ProbeTool","RectangleROI","RectangleROITool","EllipticalROI","EllipticalROITool","CircleROI","CircleROITool","Bidirectional","BidirectionalTool","Angle","AngleTool","CobbAngle","CobbAngleTool","PlanarFreehandROI","PlanarFreehandROITool","Magnify","MagnifyTool","Crosshairs","CrosshairsTool","SegmentationDisplay","SegmentationDisplayTool","ReferenceLines","ReferenceLinesTool","CalibrationLine","TrackballRotateTool","CircleScissors","CircleScissorsTool","RectangleScissors","RectangleScissorsTool","SphereScissors","SphereScissorsTool","ImageOverlayViewer","toAnnotation","measurement","toMeasurement","csToolsEventDetail","displaySetService","cornerstoneViewportService","getValueTypeFromToolType","viewportId","annotationUID","FrameOfReferenceUID","SUPPORTED_TOOLS","includes","Error","SOPInstanceUID","SeriesInstanceUID","StudyInstanceUID","getSOPInstanceAttributes","displaySet","getDisplaySetForSOPInstanceUID","getDisplaySetsForSeries","mappedAnnotations","cachedStats","keys","annotations","targetStats","frameNumber","SeriesNumber","unit","push","getMappedAnnotations","displayText","instance","images","find","image","InstanceNumber","instanceText","frameText","isMultiFrame","roundedLength","utils","roundNumber","getDisplayText","uid","referenceSeriesUID","referenceStudyUID","displaySetInstanceUID","getReport","values","join","_getReport","getHandlesFromPoints","longAxis","shortAxis","start","end","perpendicularStart","perpendicularEnd","reduce","obj","item","isAnnotationSelected","cs3dToolAnnotationUtils","setAnnotationSelected","selected","getFirstAnnotationSelected","selectedAnnotationUID","referencedSeriesInstanceUID","roundedWidth","getDisplayUnit","mean","stdDev","area","Modality","areaUnit","modalityUnit","roundedArea","mappedAnnotation","maxStr","str","DisplaySetService","CornerstoneViewportService","angle","roundedAngle","_SOPInstanceUID","_SeriesInstanceUID","measurementServiceMappingsFactory","measurementService","_getValueTypeFromToolType","toolType","POLYLINE","ELLIPSE","CIRCLE","RECTANGLE","BIDIRECTIONAL","POINT","ANGLE","MeasurementService","VALUE_TYPES","csToolsAnnotation","matchingCriteria","valueType","removeAnnotation","csToolsEvents","Enums","CORNERSTONE_3D_TOOLS_SOURCE_NAME","connectToolsToMeasurementService","csTools3DVer1MeasurementSource","initMeasurementService","createSource","addMapping","connectMeasurementServiceToTools","annotationToMeasurement","remove","addMeasurement","completedEvt","log","finally","removeMeasurement","resize","annotationRemovedEventDetail","getMeasurement","addedEvt","ANNOTATION_ADDED","ANNOTATION_COMPLETED","updatedEvt","ANNOTATION_MODIFIED","removedEvt","ANNOTATION_REMOVED","selectionEvt","ANNOTATION_SELECTION_CHANGE","eventTarget","addEventListener","annotationModifiedEventDetail","annotationSelectionEventDetail","added","addedSelectedAnnotationUIDs","removed","removedSelectedAnnotationUIDs","setMeasurementSelected","measurementSource","MEASUREMENT_REMOVED","MEASUREMENTS_CLEARED","MEASUREMENT_UPDATED","RAW_MEASUREMENT_ADDED","EVENTS","getSource","subscribe","measurements","source","name","notYetUpdatedAtSource","sourceAnnotation","_ref3","dataSource","DicomMetadataStore","getInstance","getImageIdsForInstance","addAnnotation","highlighted","isLocked","invalidated","_ref4","removedMeasurementId","render","cineService","setServiceImplementation","playClip","playClipOptions","stopClip","volumeIdMapsToLoad","viewportIdVolumeInputArrayMap","interleaveCenterLoader","volumeInputArray","displaySetsMatchDetails","viewportMatchDetails","matchDetails","volumeInput","volumeId","volume","cache","getVolume","has","size","_","details","entries","from","volumes","slice","AllRequests","requests","getImageLoadRequests","reOrderedRequests","imageIds","maxImageIdIndex","middleImageIdIndex","floor","lowerImageIdIndex","upperImageIdIndex","imageIdsToPrefetch","imageIdIndex","prefetchQueuedFilled","currentPositionDownToMinimum","currentPositionUpToMaximum","getInterleavedFrames","request","req","interleavedRequests","compact","flatten","zip","finalRequests","volumeRequests","volumeImageIdRequest","requestType","Prefetch","callLoadImage","additionalDetails","options","callLoadImageBound","bind","imageLoadPoolManager","addRequest","clear","viewportIdVolumeInputArrayMapCopy","interleaveNthLoader","lists","time","useLists","ret","list","splice","indexOf","timeEnd","interleave","frames","centerStart","centerEnd","getNthFrames","interleaveTopToBottom","reverse","findNearbyToolData","commandsManager","evt","currentPoints","runCommand","canvasCoordinates","cs3DToolsEvents","DEFAULT_CONTEXT_MENU_CLICKS","button1","commands","commandName","button3","commandOptions","requireNearbyToolData","menuId","customizationService","cornerstoneViewportHandleClick","button","which","nameArr","altKey","ctrlKey","shiftKey","getEventName","cornerstoneViewportHandleEvent","toRun","nearbyToolData","some","command","run","ELEMENT_ENABLED","getViewportInfo","setEnabledElement","MOUSE_CLICK","ELEMENT_DISABLED","removeEventListener","DEFAULT_DOUBLE_CLICK","doubleClick","cornerstoneViewportHandleDoubleClick","eventName","getDoubleClickEventName","MOUSE_DOUBLE_CLICK","TimingEnum","Types","IMAGE_TIMING_KEYS","DISPLAY_SETS_TO_ALL_IMAGES","DISPLAY_SETS_TO_FIRST_IMAGE","STUDY_TO_FIRST_IMAGE","imageTiming","viewportsWaiting","imageRenderedListener","viewportStatus","SCRIPT_TO_VIEW","IMAGE_RENDERED","init","useSharedArrayBuffer","sharedArrayBufferDisabled","csEnums","AUTO","FALSE","TRUE","cs3DInit","rendering","preferSizeOverAccuracy","useNorm16Texture","useCPURendering","strictZSpacingForVolumeViewport","maxCacheSize","setMaxCacheSize","isAnnotation","addTool","defaultStyles","getDefaultToolStyles","setDefaultToolStyles","global","textBoxFontSize","lineWidth","initCornerstoneTools","Settings","getRuntimeSettings","useCursors","uiModalService","uiNotificationService","hangingProtocolService","toolGroupService","toolbarService","stateSyncService","window","showWarningMessageForCrossOrigin","crossOriginIsolated","show","message","showCPUFallbackMessage","progress","CPUModal","unsubscribe","PROTOCOL_CHANGED","_showCPURenderingModal","register","clearOnModeExit","labelmapRepresentation","cornerstoneTools","Labelmap","fillAlpha","fillAlphaInactive","outlineOpacity","outlineOpacityInactive","metadataProvider","OHIF","MetadataProvider","registerImageLoadStrategy","nthLoader","csUtilities","maxNumRequests","interaction","thumbnail","prefetch","measurementServiceSource","initCineService","CUSTOM_IMAGE_LOAD_PERFORMED","volumeInputArrayMap","entry","getCornerstoneViewport","ohifViewport","lutPresentationStore","positionPresentationStore","presentationIds","getViewportOptions","presentations","positionPresentation","positionPresentationId","lutPresentation","lutPresentationId","setVolumesForViewport","initContextMenu","initDoubleClick","toolbarEventListener","getActiveTools","tool","toolData","getNestedButton","listeners","resetCrosshairs","renderingEngineId","toolGroup","_toolInstances","mode","Active","setToolActive","Passive","setToolPassive","Enabled","setToolEnabled","STACK_VIEWPORT_NEW_STACK","enable","CAMERA_RESET","timingKeys","initViewTiming","ACTIVE_VIEWPORT_ID_CHANGED","getToolGroupForViewport","PROGRESS","UploadStatus","UploadRejection","status","DicomFileUploader","PubSubService","file","_file","_fileId","_dataSource","_loadPromise","_abortController","AbortController","_status","NotStarted","_percentComplete","fileManager","add","getFileId","getFileName","getFileSize","cancel","abort","getStatus","getPercentComplete","load","uploadCallbacks","lengthComputable","InProgress","loaded","total","_broadcastEvent","fileId","percentComplete","timeout","_reject","Failed","Cancelled","loadFileRequest","dicomFile","signal","aborted","_checkDicomFile","XMLHttpRequest","_addRequestCallbacks","store","dicom","Success","catch","reason","_isRejected","abortCallback","upload","cleanUpCallback","arrayBuffer","arr","Uint8Array","every","char","charCodeAt","DicomUploadProgressItem","memo","dicomFileUploader","setPercentComplete","useState","failedReason","setFailedReason","setStatus","isComplete","useCallback","useEffect","progressSubscription","dicomFileUploaderProgressEvent","cancelUpload","getStatusIcon","Icon","onClick","propTypes","PropTypes","isRequired","ONE_SECOND","ONE_MINUTE","ONE_HOUR","BASE_INTERVAL_TIME","NO_WRAP_ELLIPSIS_CLASS_NAMES","DicomUploadProgress","dicomFileUploaderArr","onComplete","totalUploadSize","acc","fileUploader","currentUploadSizeRef","useRef","uploadRateRef","timeRemaining","setTimeRemaining","numFilesCompleted","setNumFilesCompleted","numFails","setNumFails","showFailedOnly","setShowFailedOnly","progressBarContainerRef","timeoutId","intervalStartUploadSize","intervalStartTime","Date","now","setUploadRateRef","uploadSizeFromStartOfInterval","current","timeSinceStartOfInterval","setTimeout","clearTimeout","currentTimeRemaining","subscriptions","currentFileUploadSize","updateProgress","previousFileUploadSize","uploadSizeRemaining","currentSecondsRemaining","ceil","delta","currentMinutesRemaining","rejection","numCompleted","progressEvent","subscription","cancelAllUploads","getFormattedTimeRemaining","secondsRemaining","minutesRemaining","hoursRemaining","getPercentCompleteRounded","showInfiniteProgressBar","offsetWidth","getNofMFilesStyle","toString","getShowFailedOnlyIconComponent","currentShowFailedOnly","Button","disabled","style","classNames","ref","ProgressLoadingBar","DicomUpload","onStarted","baseClassNames","setDicomFileUploaderArr","onDrop","acceptedFiles","Dropzone","noClick","getRootProps","_extends","noDrag","getInputProps","webkitdirectory","mozdirectory","tools","active","bindings","mouseButton","Primary","Auxiliary","Secondary","enabled","component","DEFAULT_SIZE","MAX_TEXTURE_SIZE","VIEWPORT_ID","CornerstoneViewportDownloadForm","activeViewportIdProp","activeViewportElement","activeViewportEnabledElement","ToolGroupManager","toolModeAndBindings","toolOptions","setToolMode","ViewportDownloadForm","minimumSize","maximumSize","defaultSize","canvasClass","enableViewport","viewportElement","renderingEngine","viewportInput","defaultOptions","background","orientation","enableElement","disableViewport","disableElement","updateViewportPreview","downloadViewportElement","internalCanvas","fileType","downloadViewport","updateViewport","downloadCanvas","getOrCreateCanvas","newWidth","offsetHeight","newHeight","multiplier","loadImage","getViewport","StackViewport","getCurrentImageId","properties","getProperties","setStack","setProperties","e","getActors","actor","addActor","setCamera","getCamera","toggleAnnotations","toggle","downloadViewportId","addViewport","setToolDisabled","downloadBlob","filename","divForDownloadViewport","querySelector","html2canvas","link","download","click","STACK_SYNC_NAME","toggleStackImageSync","toggledState","viewports","providedViewports","syncName","syncGroupService","getReconstructableStackViewports","gridViewport","viewportOptions","removeViewportFromSyncGroup","disableSync","addViewportToSyncGroup","displaySetInstanceUIDs","getDisplaySetByUID","isReconstructable","_getActiveViewportEnabledElement","showCornerstoneContextMenu","optionsToUse","useSelectedAnnotation","firstAnnotationSelected","allowedSelectedTools","defaultPointsPosition","selectorProps","getNearbyToolData","cstUtils","getNearbyAnnotation","toolInstance","getToolInstance","deleteMeasurement","setMeasurementLabel","_ref5","actionId","updatedMeasurement","update","updateMeasurement","props","code","textLabel","measurementKey","CodeValue","substring","CodeMeaning","CodingSchemeDesignator","findingSites","it","setViewportActive","_ref6","setActiveViewportId","arrowTextCallback","_ref7","cleanUpCrosshairs","activeViewportToolGroup","getToolGroup","toolbarServiceRecordInteraction","interactionType","context","toggleCine","isCineEnabled","setIsCineEnabled","setButton","isActive","index","setCine","isPlaying","setWindowLevel","_ref8","level","toolGroupId","windowWidthNum","windowCenterNum","viewportToolGroupId","lower","upper","csUtils","voiRange","recordInteraction","setToolbarToggled","setToggled","toolId","_ref9","duration","activeToolName","getActivePrimaryMouseButtonTool","showDownloadViewportModal","hide","rotateViewport","_ref10","rotation","currentRotation","newRotation","flipViewportHorizontal","flipHorizontal","flipViewportVertical","flipVertical","invertViewport","_ref11","invert","resetViewport","resetProperties","resetCamera","scaleViewport","_ref12","direction","scaleFactor","parallelScale","jumpToImage","_ref13","imageIndex","numberOfSlices","getImageIds","jumpIndex","scroll","_ref14","setViewportColormap","_ref15","colormap","immediate","actorEntry","volumeActor","changeActiveViewport","_ref16","viewportIds","nextViewportIndex","_ref17","setSourceViewportForReferenceLinesTool","_ref18","setToolConfiguration","sourceViewportId","storePresentation","_ref19","definitions","commandFn","storeContexts","menuCustomizationId","rotateViewportCW","rotateViewportCCW","incrementActiveViewport","decrementActiveViewport","scaleUpViewport","scaleDownViewport","fitViewportToWindow","nextImage","previousImage","firstImage","lastImage","defaultContext","mpr","locked","createdDate","modifiedDate","availableTo","editableBy","numberOfPriorsReferenced","protocolMatchingRules","imageLoadStrategy","callbacks","onLayoutChange","protocolId","onProtocolExit","displaySetSelectors","activeDisplaySet","seriesMatchingRules","weight","attribute","constraint","equals","required","stages","viewportStructure","layoutType","layoutOptions","viewportType","initialImageOptions","preset","syncGroups","displaySets","mprAnd3DVolumeViewport","mprDisplaySet","customViewportProps","hideOverlays","displayPreset","protocol","VIEWPORT_ADDED","TOOLGROUP_CREATED","ToolGroupService","serviceManager","toolGroupIds","Set","pubSubServiceInterface","onModeExit","destroy","toolGroupIdToUse","getToolGroupIds","getActiveToolForViewport","destroyToolGroup","delete","removeViewportFromToolGroup","deleteToolGroupIfEmpty","removeViewports","getViewportIds","addViewportToToolGroup","createToolGroup","addToolsToToolGroup","configs","_addTools","_setToolsMode","createToolGroupAndAddTools","getToolConfiguration","passive","addTools","parentTool","addToolInstance","REGISTRATION","altName","TOOL_GROUP_CREATED","SyncGroupService","synchronizerCreators","synchronizers","_createSynchronizer","syncCreator","toLowerCase","addSynchronizerType","creator","_getOrCreateSynchronizer","synchronizer","SynchronizerManager","isArray","syncGroup","syncGroupObj","asSyncGroup","setOptions","viewportInfo","addSource","addTarget","syncGroupId","s","sourceViewports","getSourceViewports","targetViewports","getTargetViewports","easeInOutBell","baseline","alpha","pow","COLOR_LUT","cstConstants","LABELMAP","csToolsEnums","CONTOUR","Contour","SEGMENTATION_UPDATED","SEGMENTATION_DATA_MODIFIED","SEGMENTATION_ADDED","SEGMENTATION_REMOVED","SEGMENTATION_CONFIGURATION_CHANGED","SEGMENT_LOADING_COMPLETE","SEGMENTATION_LOADING_COMPLETE","SEGMENT_CONSTANT","opacity","isVisible","SegmentationService","_this","segmentations","highlightIntervalId","SEGMENTATION_MODIFIED","_onSegmentationModifiedFromSource","_onSegmentationDataModified","segmentationId","_removeSegmentationFromCornerstone","setSegmentRGBA","segmentIndex","rgbaColor","segmentation","getSegmentation","_setSegmentOpacity","_setSegmentColor","calculateCentroids","getLabelmapVolume","dimensions","scalarData","getScalarData","dimX","dimY","numFrames","frameLength","segmentIndices","segments","segment","segmentIndicesSet","centroids","z","count","voxelIndex","frame","centroid","result","normalizedCentroid","world","indexToWorld","setCentroids","segmentCenter","center","addOrUpdateSegmentation","createSegmentationForDisplaySet","representationType","_getVolumeIdForDisplaySet","targetBuffer","sharedArrayBuffer","SharedArrayBuffer","_getDefaultSegmentationScheme","instances","representationData","referencedVolumeId","toggleSegmentationVisibility","_toggleSegmentationVisibility","addSegmentationRepresentationToToolGroup","hydrateSegmentation","suppressEvents","hydrated","colorLUTIndex","segmentationRepresentationUIDs","cstSegmentation","_setActiveSegmentationForToolGroup","visibility","_setSegmentVisibility","_setSegmentLocked","setSegmentRGBAColor","getToolGroupIdsWithSegmentation","_setDisplaySetIsHydrated","getConfiguration","_getApplicableToolGroupId","segmentationRepresentations","getSegmentationRepresentationsForToolGroup","typeToUse","renderInactiveSegmentations","representation","representations","renderOutline","outlineWidthActive","renderFill","brushSize","brushThresholdGate","setConfiguration","setConfigValueIfDefined","transformFn","transformedValue","_setSegmentationConfig","_updateCornerstoneSegmentationVisibility","segmentInfo","_getSegmentInfo","segmentationRepresentation","_getSegmentationRepresentation","segmentationRepresentationUID","property","getSegmentations","renderViewports","segmentationState","activeSegmentIndex","segmentsLocked","segmentationSchema","segmentsHidden","newVisibility","_getSegmentationInfo","getActiveViewportId","getToolGroupId","getNextColorLUTIndex","arrayOfObjects","_initSegmentationService","addSegment","segmentCount","_setActiveSegment","newColor","removeSegment","labelmapVolume","modifiedFrames","modifiedFramesArray","newActiveSegmentIndex","setSegmentVisibility","setSegmentLocked","toggleSegmentLocked","setSegmentColor","setSegmentOpacity","setActiveSegmentationForToolGroup","setActiveSegment","filterNonHydratedSegmentations","_getSegmentations","m","getActiveSegmentation","getActiveSegment","activeSegmentation","cachedSegmentation","_updateCornerstoneSegmentations","newColorLUT","generateNewColorLUT","createSegmentationForSEGDisplaySet","segDisplaySet","SeriesDescription","labelmap","labelmapBufferArray","derivedVolume","derivedVolumeScalarData","segmentsInfo","segMetadata","SegmentedPropertyCategoryCodeSequence","SegmentNumber","SegmentLabel","SegmentAlgorithmType","SegmentAlgorithmName","SegmentedPropertyTypeCodeSequence","rgba","centerWorld","modifiedTime","SeriesDate","category","algorithmType","algorithmName","isLoaded","createSegmentationForRTDisplaySet","rtDisplaySet","structureSet","defaultScheme","rtDisplaySetUID","allRTStructData","ROIContours","contourPoints","ROINumber","ROIName","colorArray","rest","geometryId","mapROIContoursToRTStructData","sort","a","b","geometryIds","segmentsCachedStats","initializeContour","rtStructData","geometry","geometryLoader","geometryData","frameOfReferenceUID","getCentroid","numInitialized","numSegments","promiseArray","promise","jumpToSegmentCenter","highlightAlpha","highlightSegment","animationLength","highlightHideOthers","highlightFunctionType","_getSegmentCenter","_getToolGroupIdsWithSegmentation","toolGroups","viewportsInfo","getViewportsInfo","getEnabledElementByIds","hideOthers","clearInterval","_highlightLabelmap","_highlightContour","displaySetUID","isHydrated","setDisplaySetMetadataInvalidated","newSegmentSpecificConfig","startTime","animation","timestamp","elapsed","requestAnimationFrame","performance","animate","currentTime","reversedProgress","removeSegmentationRepresentationFromToolGroup","segmentationRepresentationUIDsIds","uids","rep","wasActive","remainingHydratedSegmentations","setSegmentLabel","_setSegmentLabel","shouldRenderSegmentation","viewportDisplaySetInstanceUIDs","segmentationFrameOfReferenceUID","shouldDisplaySeg","targetSegmentation","volumeLoaderSchema","segmentLabel","getSegmentationRepresentations","UIDsToRemove","removeSegmentation","getVolumeLoadObject","removeVolumeLoadObject","sourceSegmentation","isEqual","_getFrameOfReferenceUIDForSeg","referencedFrameOfReferenceSequence","ReferencedFrameOfReferenceSequence","cloneDeep","getCornerstoneViewportType","lowerViewportType","STACK","ORTHOGRAPHIC","VOLUME_3D","VOLUME_LOADER_SCHEME","CornerstoneCacheService","stackImageIds","volumeImageIds","getCacheSize","cs3DCache","getCacheFreeSpace","getBytesAvailable","createViewportData","initialImageIndex","_shouldRenderSegmentation","cs3DViewportType","viewportData","_getStackViewportData","_getVolumeViewportData","invalidateViewportData","invalidatedDisplaySetInstanceUID","_getCornerstoneStackImageIds","isCompositeStack","StackViewportData","volumeData","Function","studyInstanceUID","_getCornerstoneVolumeImageIds","segmentationService","segDisplaySetInstanceUID","getImageIdsForDisplaySet","RENDERING_ENGINE_ID","DEFAULT_TOOLGROUP_ID","dataContains","dataId","displaySetOptions","setPublicViewportOptions","setPublicDisplaySetOptions","contains","setRenderingEngineId","getRenderingEngineId","setViewportId","setElement","setViewportData","getViewportData","getElement","getViewportId","publicDisplaySetOptions","mapDisplaySetOptions","setDisplaySetOptions","hasDisplaySet","dsUID","viewportOptionsEntry","AXIAL","SAGITTAL","CORONAL","ACQUISITION","getCornerstoneOrientation","setViewportOptions","getSyncGroups","getDisplaySetOptions","getViewportType","getBackground","getOrientation","getDisplayArea","displayArea","getInitialImageOptions","option","blendMode","slabThickness","voi","voiInverted","COMPOSITE","MAXIMUM_INTENSITY_BLEND","getCornerstoneBlendMode","JumpPresets","VIEWPORT_DATA_CHANGED","viewportsById","viewportGridResizeObserver","viewportsDisplaySets","enableResizeDetector","resizeRefreshRateMs","resizeRefreshMode","elementRef","ViewportInfo","hasBeenDestroyed","RenderingEngine","_removeResizeObserver","purgeCache","setPresentations","camera","getPresentation","csViewport","isComputedVOI","VOILUTFunction","getCurrentImageIdIndex","presentation","storeState","publicViewportOptions","_setDisplaySets","_setStackViewport","initialImageIndexToUse","_getInitialImageIndexForViewport","windowWidth","windowCenter","imageSliceData","_getInitialImageIndex","lastSliceIndex","csToolsUtils","First","Last","Middle","_setVolumeViewport","displaySetOptionsArray","volumeToLoad","_getSlabThickness","getShouldPerformCustomImageLoad","runImageLoadStrategy","loadStatus","loading","volumesProperties","displaySetOption","setVolumes","overlayDisplaySet","isOverlayDisplaySet","addOverlayRepresentationForDisplaySet","_addSegmentationRepresentationToToolGroupIfNecessary","segFrameOfReferenceUID","_getFrameOfReferenceUID","keepCamera","viewportCamera","VolumeViewport3D","disconnect","imageVolume","getViewportIdToJump","cameraProps","getImageId","imageObj","url","someInvalidStrings","strings","string","getImageInstance","dataset","getImageInstanceId","imageInstance","fetchIt","DICOMWeb","fetch","response","cornerstoneRetriever","imageLoader","byteArray","buffer","wadorsRetriever","seriesInstanceUID","sopInstanceUID","api","DICOMwebClient","retrieveInstance","getLocalData","studies","nonImageInstance","getNonImageInstance","startsWith","findImageIdOnStudies","study","series","getDataByImageType","getDicomDataMethod","loaderType","loaderRegExp","exec","lastIndex","replace","getImageLoaderType","getData","wadoRoot","getStudyInstanceUID","getSeriesInstanceUID","getSOPInstanceUID","getDataByDatasetType","authorizationHeaders","wadoUri","getLoaderIterator","findDicomDataPromise","loaderIterator","loader","packageJson","Component","OHIFCornerstoneViewport","fallback","cs3DEnums","clearRequestStack","imageRetrievalPoolManager","enabledElementReset","preRegistration","registerService","call","getHangingProtocolModule","getViewportModule","getCommandsModule","getCustomizationModule","getUtilityModule","exports","getCornerstoneLibraries","dicomLoaderService","cs3DToolsEnums","state","DEFAULT_CONTEXT","enabledElements","targetContext","reset","_getUIDFromImageID"],"sourceRoot":""}