diff --git a/.webpack/webpack.base.js b/.webpack/webpack.base.js index 6efedd0d2..aa48230d1 100644 --- a/.webpack/webpack.base.js +++ b/.webpack/webpack.base.js @@ -120,6 +120,17 @@ module.exports = (env, argv, { SRC_DIR, ENTRY }) => { test: /\.wasm/, type: 'asset/resource', }, + { + test: /\.(png|jpe?g|gif|svg)$/i, + use: [ + { + loader: 'file-loader', + options: { + name: 'assets/images/[name].[ext]', + }, + }, + ], + }, ], //.concat(vtkRules), }, resolve: { diff --git a/extensions/cornerstone-dicom-rt/src/viewports/OHIFCornerstoneRTViewport.tsx b/extensions/cornerstone-dicom-rt/src/viewports/OHIFCornerstoneRTViewport.tsx index 5c6a844dd..bef64b145 100644 --- a/extensions/cornerstone-dicom-rt/src/viewports/OHIFCornerstoneRTViewport.tsx +++ b/extensions/cornerstone-dicom-rt/src/viewports/OHIFCornerstoneRTViewport.tsx @@ -1,13 +1,11 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import PropTypes from 'prop-types'; -import OHIF, { utils } from '@ohif/core'; -import { ViewportActionBar, useViewportGrid, LoadingIndicatorTotalPercent } from '@ohif/ui'; +import { useViewportGrid, LoadingIndicatorTotalPercent, ViewportActionArrows } from '@ohif/ui'; import promptHydrateRT from '../utils/promptHydrateRT'; import _getStatusComponent from './_getStatusComponent'; import createRTToolGroupAndAddTools from '../utils/initRTToolGroup'; -const { formatDate } = utils; const RT_TOOLGROUP_BASE_NAME = 'RTToolGroup'; function OHIFCornerstoneRTViewport(props) { @@ -15,7 +13,6 @@ function OHIFCornerstoneRTViewport(props) { children, displaySets, viewportOptions, - viewportLabel, servicesManager, extensionManager, commandsManager, @@ -27,6 +24,7 @@ function OHIFCornerstoneRTViewport(props) { segmentationService, uiNotificationService, customizationService, + viewportActionCornersService, } = servicesManager.services; const viewportId = viewportOptions.viewportId; @@ -126,7 +124,6 @@ function OHIFCornerstoneRTViewport(props) { const onSegmentChange = useCallback( direction => { - direction = direction === 'left' ? -1 : 1; const segmentationId = rtDisplaySet.displaySetInstanceUID; const segmentation = segmentationService.getSegmentation(segmentationId); @@ -282,20 +279,7 @@ function OHIFCornerstoneRTViewport(props) { }); } - const { - PatientID, - PatientName, - PatientSex, - PatientAge, - SliceThickness, - ManufacturerModelName, - StudyDate, - SeriesDescription, - SpacingBetweenSlices, - SeriesNumber, - } = referencedDisplaySetRef.current.metadata; - - const onStatusClick = async () => { + const onStatusClick = useCallback(async () => { // Before hydrating a RT and make it added to all viewports in the grid // that share the same frameOfReferenceUID, we need to store the viewport grid // presentation state, so that we can restore it after hydrating the RT. This is @@ -309,41 +293,47 @@ function OHIFCornerstoneRTViewport(props) { }); setIsHydrated(isHydrated); - }; + }, [hydrateRTDisplaySet, rtDisplaySet, storePresentationState, viewportId]); + + useEffect(() => { + viewportActionCornersService.setComponents([ + { + viewportId, + id: 'viewportStatusComponent', + component: _getStatusComponent({ + isHydrated, + onStatusClick, + }), + indexPriority: -100, + location: viewportActionCornersService.LOCATIONS.topLeft, + }, + { + viewportId, + id: 'viewportActionArrowsComponent', + component: ( + + ), + indexPriority: 0, + location: viewportActionCornersService.LOCATIONS.topRight, + }, + ]); + }, [ + activeViewportId, + isHydrated, + onSegmentChange, + onStatusClick, + viewportActionCornersService, + viewportId, + ]); return ( <> - { - evt.stopPropagation(); - evt.preventDefault(); - }} - onArrowsClick={onSegmentChange} - getStatusComponent={() => { - return _getStatusComponent({ - isHydrated, - onStatusClick, - }); - }} - studyData={{ - label: viewportLabel, - useAltStyling: true, - studyDate: formatDate(StudyDate), - currentSeries: SeriesNumber, - seriesDescription: `RT Viewport ${SeriesDescription}`, - patientInformation: { - patientName: PatientName ? OHIF.utils.formatPN(PatientName.Alphabetic) : '', - patientSex: PatientSex || '', - patientAge: PatientAge || '', - MRN: PatientID || '', - thickness: SliceThickness ? `${SliceThickness.toFixed(2)}mm` : '', - spacing: - SpacingBetweenSlices !== undefined ? `${SpacingBetweenSlices.toFixed(2)}mm` : '', - scanner: ManufacturerModelName || '', - }, - }} - /> -
{rtIsLoading && ( ; @@ -26,23 +23,28 @@ export default function _getStatusComponent({ isHydrated, onStatusClick }) { ToolTipMessage = () =>
Click LOAD to load RTSTRUCT.
; } - const StatusArea = () => ( -
-
- - RTSTRUCT -
- {!isHydrated && ( -
- {loadStr} + const StatusArea = () => { + const { t } = useTranslation('Common'); + const loadStr = t('LOAD'); + + return ( +
+
+ + RTSTRUCT
- )} -
- ); + {!isHydrated && ( +
+ {loadStr} +
+ )} +
+ ); + }; return ( <> diff --git a/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx b/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx index 0d14c68f5..d14e720de 100644 --- a/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx +++ b/extensions/cornerstone-dicom-seg/src/viewports/OHIFCornerstoneSEGViewport.tsx @@ -1,13 +1,11 @@ import PropTypes from 'prop-types'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import OHIF, { utils } from '@ohif/core'; -import { LoadingIndicatorTotalPercent, useViewportGrid, ViewportActionBar } from '@ohif/ui'; +import { LoadingIndicatorTotalPercent, useViewportGrid, ViewportActionArrows } from '@ohif/ui'; import createSEGToolGroupAndAddTools from '../utils/initSEGToolGroup'; import promptHydrateSEG from '../utils/promptHydrateSEG'; import _getStatusComponent from './_getStatusComponent'; -const { formatDate } = utils; const SEG_TOOLGROUP_BASE_NAME = 'SEGToolGroup'; function OHIFCornerstoneSEGViewport(props) { @@ -15,7 +13,6 @@ function OHIFCornerstoneSEGViewport(props) { children, displaySets, viewportOptions, - viewportLabel, servicesManager, extensionManager, commandsManager, @@ -30,6 +27,7 @@ function OHIFCornerstoneSEGViewport(props) { segmentationService, uiNotificationService, customizationService, + viewportActionCornersService, } = servicesManager.services; const toolGroupId = `${SEG_TOOLGROUP_BASE_NAME}-${viewportId}`; @@ -122,7 +120,6 @@ function OHIFCornerstoneSEGViewport(props) { const onSegmentChange = useCallback( direction => { - direction = direction === 'left' ? -1 : 1; const segmentationId = segDisplaySet.displaySetInstanceUID; const segmentation = segmentationService.getSegmentation(segmentationId); @@ -247,6 +244,69 @@ function OHIFCornerstoneSEGViewport(props) { }; }, [segDisplaySet]); + const hydrateSEGDisplaySet = useCallback( + ({ segDisplaySet, viewportId }) => { + commandsManager.runCommand('loadSegmentationDisplaySetsForViewport', { + displaySets: [segDisplaySet], + viewportId, + }); + }, + [commandsManager] + ); + + const onStatusClick = useCallback(async () => { + // Before hydrating a SEG and make it added to all viewports in the grid + // that share the same frameOfReferenceUID, we need to store the viewport grid + // presentation state, so that we can restore it after hydrating the SEG. This is + // required if the user has changed the viewport (other viewport than SEG viewport) + // presentation state (w/l and invert) and then opens the SEG. If we don't store + // the presentation state, the viewport will be reset to the default presentation + storePresentationState(); + const isHydrated = await hydrateSEGDisplaySet({ + segDisplaySet, + viewportId, + }); + + setIsHydrated(isHydrated); + }, [hydrateSEGDisplaySet, segDisplaySet, storePresentationState, viewportId]); + + useEffect(() => { + viewportActionCornersService.setComponents([ + { + viewportId, + id: 'viewportStatusComponent', + component: _getStatusComponent({ + isHydrated, + onStatusClick, + }), + indexPriority: -100, + location: viewportActionCornersService.LOCATIONS.topLeft, + }, + { + viewportId, + id: 'viewportActionArrowsComponent', + component: ( + + ), + indexPriority: 0, + location: viewportActionCornersService.LOCATIONS.topRight, + }, + ]); + }, [ + activeViewportId, + isHydrated, + onSegmentChange, + onStatusClick, + viewportActionCornersService, + viewportId, + ]); + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ let childrenWithProps = null; @@ -282,61 +342,8 @@ function OHIFCornerstoneSEGViewport(props) { SpacingBetweenSlices, } = referencedDisplaySetRef.current.metadata; - const hydrateSEGDisplaySet = ({ segDisplaySet, viewportId }) => { - commandsManager.runCommand('loadSegmentationDisplaySetsForViewport', { - displaySets: [segDisplaySet], - viewportId, - }); - }; - - const onStatusClick = async () => { - // Before hydrating a SEG and make it added to all viewports in the grid - // that share the same frameOfReferenceUID, we need to store the viewport grid - // presentation state, so that we can restore it after hydrating the SEG. This is - // required if the user has changed the viewport (other viewport than SEG viewport) - // presentation state (w/l and invert) and then opens the SEG. If we don't store - // the presentation state, the viewport will be reset to the default presentation - storePresentationState(); - const isHydrated = await hydrateSEGDisplaySet({ - segDisplaySet, - viewportId, - }); - - setIsHydrated(isHydrated); - }; return ( <> - { - evt.stopPropagation(); - evt.preventDefault(); - }} - onArrowsClick={onSegmentChange} - getStatusComponent={() => { - return _getStatusComponent({ - isHydrated, - onStatusClick, - }); - }} - studyData={{ - label: viewportLabel, - useAltStyling: true, - studyDate: formatDate(StudyDate), - seriesDescription: `SEG Viewport ${SeriesDescription}`, - patientInformation: { - patientName: PatientName ? OHIF.utils.formatPN(PatientName.Alphabetic) : '', - patientSex: PatientSex || '', - patientAge: PatientAge || '', - MRN: PatientID || '', - thickness: SliceThickness ? utils.roundNumber(SliceThickness, 2) : '', - thicknessUnits: SliceThickness !== undefined ? 'mm' : '', - spacing: - SpacingBetweenSlices !== undefined ? utils.roundNumber(SpacingBetweenSlices, 2) : '', - scanner: ManufacturerModelName || '', - }, - }} - /> -
{segIsLoading && ( ; @@ -26,23 +23,28 @@ export default function _getStatusComponent({ isHydrated, onStatusClick }) { ToolTipMessage = () =>
Click LOAD to load segmentation.
; } - const StatusArea = () => ( -
-
- - SEG -
- {!isHydrated && ( -
- {loadStr} + const StatusArea = () => { + const { t } = useTranslation('Common'); + const loadStr = t('LOAD'); + + return ( +
+
+ + SEG
- )} -
- ); + {!isHydrated && ( +
+ {loadStr} +
+ )} +
+ ); + }; return ( <> diff --git a/extensions/cornerstone-dicom-sr/src/viewports/OHIFCornerstoneSRViewport.tsx b/extensions/cornerstone-dicom-sr/src/viewports/OHIFCornerstoneSRViewport.tsx index 0937ca1ff..849813c57 100644 --- a/extensions/cornerstone-dicom-sr/src/viewports/OHIFCornerstoneSRViewport.tsx +++ b/extensions/cornerstone-dicom-sr/src/viewports/OHIFCornerstoneSRViewport.tsx @@ -1,35 +1,30 @@ import PropTypes from 'prop-types'; import React, { useCallback, useContext, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import OHIF, { utils, ServicesManager, ExtensionManager } from '@ohif/core'; +import { ServicesManager, ExtensionManager } from '@ohif/core'; import { setTrackingUniqueIdentifiersForElement } from '../tools/modules/dicomSRModule'; -import { Icon, Tooltip, useViewportGrid, ViewportActionBar } from '@ohif/ui'; +import { Icon, Tooltip, useViewportGrid, ViewportActionArrows } from '@ohif/ui'; import hydrateStructuredReport from '../utils/hydrateStructuredReport'; import { useAppConfig } from '@state'; -const { formatDate } = utils; - const MEASUREMENT_TRACKING_EXTENSION_ID = '@ohif/extension-measurement-tracking'; const SR_TOOLGROUP_BASE_NAME = 'SRToolGroup'; function OHIFCornerstoneSRViewport(props) { - const { - children, - dataSource, - displaySets, - viewportLabel, - viewportOptions, - servicesManager, - extensionManager, - } = props; + const { children, dataSource, displaySets, viewportOptions, servicesManager, extensionManager } = + props; const [appConfig] = useAppConfig(); - const { displaySetService, cornerstoneViewportService, measurementService } = - servicesManager.services; + const { + displaySetService, + cornerstoneViewportService, + measurementService, + viewportActionCornersService, + } = servicesManager.services; const viewportId = viewportOptions.viewportId; @@ -48,6 +43,8 @@ function OHIFCornerstoneSRViewport(props) { const [element, setElement] = useState(null); const { viewports, activeViewportId } = viewportGrid; + const { t } = useTranslation('Common'); + // Optional hook into tracking extension, if present. let trackedMeasurements; let sendTrackedMeasurementsEvent; @@ -213,18 +210,11 @@ function OHIFCornerstoneSRViewport(props) { direction => { let newMeasurementSelected = measurementSelected; - if (direction === 'right') { - newMeasurementSelected++; - - if (newMeasurementSelected >= measurementCount) { - newMeasurementSelected = 0; - } - } else { - newMeasurementSelected--; - - if (newMeasurementSelected < 0) { - newMeasurementSelected = measurementCount - 1; - } + newMeasurementSelected += direction; + if (newMeasurementSelected >= measurementCount) { + newMeasurementSelected = 0; + } else if (newMeasurementSelected < 0) { + newMeasurementSelected = measurementCount - 1; } setTrackingIdentifiers(newMeasurementSelected); @@ -298,6 +288,46 @@ function OHIFCornerstoneSRViewport(props) { updateViewport(measurementSelected); }, [dataSource, srDisplaySet]); + useEffect(() => { + viewportActionCornersService.setComponents([ + { + viewportId, + id: 'viewportStatusComponent', + component: _getStatusComponent({ + srDisplaySet, + viewportId, + isRehydratable: srDisplaySet.isRehydratable, + isLocked, + sendTrackedMeasurementsEvent, + t, + }), + indexPriority: -100, + location: viewportActionCornersService.LOCATIONS.topLeft, + }, + { + viewportId, + id: 'viewportActionArrowsComponent', + index: 0, + component: ( + + ), + indexPriority: 0, + location: viewportActionCornersService.LOCATIONS.topRight, + }, + ]); + }, [ + isLocked, + onMeasurementChange, + sendTrackedMeasurementsEvent, + srDisplaySet, + t, + viewportActionCornersService, + viewportId, + ]); + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ let childrenWithProps = null; @@ -317,57 +347,8 @@ function OHIFCornerstoneSRViewport(props) { }); } - const { - PatientID, - PatientName, - PatientSex, - PatientAge, - SliceThickness, - ManufacturerModelName, - StudyDate, - SeriesDescription, - SpacingBetweenSlices, - SeriesNumber, - } = referencedDisplaySetMetadata; - - // TODO -> disabled double click for now: onDoubleClick={_onDoubleClick} return ( <> - { - evt.stopPropagation(); - evt.preventDefault(); - }} - onArrowsClick={onMeasurementChange} - getStatusComponent={() => - _getStatusComponent({ - srDisplaySet, - viewportId, - isTracked: false, - isRehydratable: srDisplaySet.isRehydratable, - isLocked, - sendTrackedMeasurementsEvent, - }) - } - studyData={{ - label: viewportLabel, - useAltStyling: true, - studyDate: formatDate(StudyDate), - currentSeries: SeriesNumber, - seriesDescription: SeriesDescription || '', - patientInformation: { - patientName: PatientName ? OHIF.utils.formatPN(PatientName.Alphabetic) : '', - patientSex: PatientSex || '', - patientAge: PatientAge || '', - MRN: PatientID || '', - thickness: SliceThickness ? `${parseFloat(SliceThickness).toFixed(2)}mm` : '', - spacing: - SpacingBetweenSlices !== undefined ? `${SpacingBetweenSlices.toFixed(2)}mm` : '', - scanner: ManufacturerModelName || '', - }, - }} - /> -
{getCornerstoneViewport()} {childrenWithProps} @@ -384,7 +365,6 @@ OHIFCornerstoneSRViewport.propTypes = { viewportLabel: PropTypes.string, customProps: PropTypes.object, viewportOptions: PropTypes.object, - viewportLabel: PropTypes.string, servicesManager: PropTypes.instanceOf(ServicesManager).isRequired, extensionManager: PropTypes.instanceOf(ExtensionManager).isRequired, }; @@ -429,6 +409,7 @@ function _getStatusComponent({ isRehydratable, isLocked, sendTrackedMeasurementsEvent, + t, }) { const handleMouseUp = () => { sendTrackedMeasurementsEvent('HYDRATE_SR', { @@ -437,7 +418,6 @@ function _getStatusComponent({ }); }; - const { t } = useTranslation('Common'); const loadStr = t('LOAD'); // 1 - Incompatible diff --git a/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx b/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx index 389672f05..44810f1b1 100644 --- a/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx +++ b/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx @@ -10,7 +10,7 @@ import { utilities as csUtils, } from '@cornerstonejs/core'; import { MeasurementService } from '@ohif/core'; -import { Notification, useViewportDialog } from '@ohif/ui'; +import { Notification, useViewportDialog, Types as UITypes, AllInOneMenu } from '@ohif/ui'; import { IStackViewport, IVolumeViewport } from '@cornerstonejs/core/dist/esm/types'; import { setEnabledElement } from '../state'; @@ -21,6 +21,11 @@ import getSOPInstanceAttributes from '../utils/measurementServiceMappings/utils/ import CornerstoneServices from '../types/CornerstoneServices'; import CinePlayer from '../components/CinePlayer'; import { Types } from '@ohif/core'; + +import OHIFViewportActionCorners from '../components/OHIFViewportActionCorners'; +import { getWindowLevelActionMenu } from '../components/WindowLevelActionMenu/getWindowLevelActionMenu'; +import { useAppConfig } from '@state'; + import { LutPresentation, PositionPresentation } from '../types/Presentation'; const STACK = 'stack'; @@ -116,6 +121,7 @@ const OHIFCornerstoneViewport = React.memo(props => { const [scrollbarHeight, setScrollbarHeight] = useState('100px'); const [enabledVPElement, setEnabledVPElement] = useState(null); const elementRef = useRef(); + const [appConfig] = useAppConfig(); const { measurementService, @@ -127,12 +133,14 @@ const OHIFCornerstoneViewport = React.memo(props => { cornerstoneCacheService, viewportGridService, stateSyncService, + viewportActionCornersService, + customizationService, } = servicesManager.services as CornerstoneServices; const [viewportDialogState] = useViewportDialog(); // useCallback for scroll bar height calculation const setImageScrollBarHeight = useCallback(() => { - const scrollbarHeight = `${elementRef.current.clientHeight - 20}px`; + const scrollbarHeight = `${elementRef.current.clientHeight - 40}px`; setScrollbarHeight(scrollbarHeight); }, [elementRef]); @@ -152,6 +160,8 @@ const OHIFCornerstoneViewport = React.memo(props => { toolGroupService.removeViewportFromToolGroup(viewportId, renderingEngineId); syncGroupService.removeViewportFromSyncGroup(viewportId, renderingEngineId, syncGroups); + + viewportActionCornersService.clear(viewportId); }, [viewportId] ); @@ -361,6 +371,34 @@ const OHIFCornerstoneViewport = React.memo(props => { }; }, [displaySets, elementRef, viewportId]); + // Set up the window level action menu in the viewport action corners. + useEffect(() => { + // Doing an === check here because the default config value when not set is true + if (appConfig.addWindowLevelActionMenu === false) { + return; + } + + // TODO: In the future we should consider using the customization service + // to determine if and in which corner various action components should go. + const wlActionMenu = getWindowLevelActionMenu({ + viewportId, + element: elementRef.current, + displaySets, + servicesManager, + commandsManager, + verticalDirection: AllInOneMenu.VerticalDirection.TopToBottom, + horizontalDirection: AllInOneMenu.HorizontalDirection.RightToLeft, + }); + + viewportActionCornersService.setComponent({ + viewportId, + id: 'windowLevelActionMenu', + component: wlActionMenu, + location: viewportActionCornersService.LOCATIONS.topRight, + indexPriority: -100, + }); + }, [displaySets, viewportId, viewportActionCornersService, servicesManager, commandsManager]); + return (
@@ -388,7 +426,8 @@ const OHIFCornerstoneViewport = React.memo(props => { servicesManager={servicesManager} />
-
+ {/* top offset of 24px to account for ViewportActionCorners. */} +
{viewportDialogState.viewportId === viewportId && ( { /> )}
+ {/* The OHIFViewportActionCorners follows the viewport in the DOM so that it is naturally at a higher z-index.*/} + ); }, areEqual); diff --git a/extensions/cornerstone/src/Viewport/Overlays/CustomizableViewportOverlay.tsx b/extensions/cornerstone/src/Viewport/Overlays/CustomizableViewportOverlay.tsx index 0858f9089..5349481a8 100644 --- a/extensions/cornerstone/src/Viewport/Overlays/CustomizableViewportOverlay.tsx +++ b/extensions/cornerstone/src/Viewport/Overlays/CustomizableViewportOverlay.tsx @@ -80,10 +80,13 @@ function CustomizableViewportOverlay({ 'cornerstoneOverlayBottomRight' ); - const instance = useMemo( - () => (viewportData ? getViewportInstance(viewportData, imageIndex) : null), - [viewportData, imageIndex] - ); + const instance = useMemo(() => { + if (viewportData != null) { + return _getViewportInstance(viewportData, imageIndex); + } else { + return null; + } + }, [viewportData, imageIndex]); const instanceNumber = useMemo( () => @@ -220,7 +223,7 @@ function CustomizableViewportOverlay({ {items.map((item, index) => (
{item?.condition - ? item.condition() + ? item.condition({ instance, formatters: { formatDate: formatDICOMDate } }) ? _renderOverlayItem(item) : null : _renderOverlayItem(item)} @@ -242,56 +245,72 @@ function CustomizableViewportOverlay({ topLeftCustomization, [ { - id: 'WindowLevel', - customizationType: 'ohif.overlayItem.windowLevel', + id: 'StudyDate', + customizationType: 'ohif.overlayItem', + label: '', + title: 'Study date', + condition: ({ instance }) => instance && instance.StudyDate, + contentF: ({ instance, formatters: { formatDate } }) => + formatDate(instance.StudyDate), }, { - id: 'ZoomLevel', - customizationType: 'ohif.overlayItem.zoomLevel', - condition: () => { - const activeToolName = toolGroupService.getActiveToolForViewport(viewportId); - return activeToolName === 'Zoom'; - }, + id: 'SeriesDescription', + customizationType: 'ohif.overlayItem', + label: '', + title: 'Series description', + attribute: 'SeriesDescription', + condition: ({ instance }) => instance && instance.SeriesDescription, }, ], 'topLeftOverlayItem' ) } - topRight={getContent( - topRightCustomization, + topRight={getContent(topRightCustomization, [], 'topRightOverlayItem')} + bottomLeft={getContent( + bottomLeftCustomization, + [ + { + id: 'WindowLevel', + customizationType: 'ohif.overlayItem.windowLevel', + }, + { + id: 'ZoomLevel', + customizationType: 'ohif.overlayItem.zoomLevel', + condition: () => { + const activeToolName = toolGroupService.getActiveToolForViewport(viewportId); + return activeToolName === 'Zoom'; + }, + }, + ], + 'bottomLeftOverlayItem' + )} + bottomRight={getContent( + bottomRightCustomization, [ { id: 'InstanceNumber', customizationType: 'ohif.overlayItem.instanceNumber', }, ], - 'topRightOverlayItem' + 'bottomRightOverlayItem' )} - bottomLeft={getContent(bottomLeftCustomization, [null], 'bottomLeftOverlayItem')} - bottomRight={getContent(bottomRightCustomization, [null], 'bottomRightOverlayItem')} /> ); } -const getViewportInstance = (viewportData, imageIndex) => { - const { viewportType, data } = viewportData; +function _getViewportInstance(viewportData, imageIndex) { let imageId = null; - - switch (viewportType) { - case Enums.ViewportType.STACK: - imageId = data.imageIds[imageIndex]; - break; - case Enums.ViewportType.ORTHOGRAPHIC: - if (data?.length === 1) { - imageId = data[0].imageIds[imageIndex]; - } - break; - default: - break; + if (viewportData.viewportType === Enums.ViewportType.STACK) { + imageId = viewportData.data.imageIds[imageIndex]; + } else if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC) { + const volumes = viewportData.data; + if (volumes && volumes.length == 1) { + const volume = volumes[0]; + imageId = volume.imageIds[imageIndex]; + } } - return imageId ? metaData.get('instance', imageId) || {} : {}; -}; +} const getInstanceNumber = (viewportData, viewportId, imageIndex, cornerstoneViewportService) => { let instanceNumber; @@ -389,9 +408,9 @@ function VOIOverlayItem({ voi, customization }: OverlayItemProps) { style={{ color: (customization && customization.color) || undefined }} > W: - {windowWidth.toFixed(0)} + {windowWidth.toFixed(0)} L: - {windowCenter.toFixed(0)} + {windowCenter.toFixed(0)}
); } @@ -406,7 +425,7 @@ function ZoomOverlayItem({ scale, customization }: OverlayItemProps) { style={{ color: (customization && customization.color) || undefined }} > Zoom: - {scale.toFixed(2)}x + {scale.toFixed(2)}x
); } @@ -427,7 +446,7 @@ function InstanceNumberOverlayItem({ style={{ color: (customization && customization.color) || undefined }} > I: - + {instanceNumber !== undefined && instanceNumber !== null ? `${instanceNumber} (${imageIndex + 1}/${numberOfSlices})` : `${imageIndex + 1}/${numberOfSlices}`} diff --git a/extensions/cornerstone/src/Viewport/Overlays/ViewportOrientationMarkers.tsx b/extensions/cornerstone/src/Viewport/Overlays/ViewportOrientationMarkers.tsx index 2f33456a4..45b85b705 100644 --- a/extensions/cornerstone/src/Viewport/Overlays/ViewportOrientationMarkers.tsx +++ b/extensions/cornerstone/src/Viewport/Overlays/ViewportOrientationMarkers.tsx @@ -108,17 +108,15 @@ function ViewportOrientationMarkers({ console.log('ViewportOrientationMarkers::No viewport'); return null; } - const backgroundColor = ohifViewport.getViewportOptions().background; - - // Todo: probably this can be done in a better way in which we identify bright - // background - const isLight = backgroundColor ? csUtils.isEqual(backgroundColor, [1, 1, 1]) : false; return orientationMarkers.map((m, index) => (
@@ -135,7 +133,7 @@ function ViewportOrientationMarkers({ element, ]); - return
{markers}
; + return
{markers}
; } ViewportOrientationMarkers.propTypes = { diff --git a/extensions/cornerstone/src/commandsModule.ts b/extensions/cornerstone/src/commandsModule.ts index cef68c8fa..d70da2b6e 100644 --- a/extensions/cornerstone/src/commandsModule.ts +++ b/extensions/cornerstone/src/commandsModule.ts @@ -40,6 +40,8 @@ function commandsModule({ cornerstoneViewportService, uiNotificationService, measurementService, + colorbarService, + hangingProtocolService, syncGroupService, } = servicesManager.services as CornerstoneServices; @@ -239,18 +241,12 @@ function commandsModule({ cineService.setIsCineEnabled(!isCineEnabled); viewports.forEach((_, index) => cineService.setCine({ id: index, isPlaying: false })); }, - setWindowLevel({ window, level, toolGroupId }) { + + setViewportWindowLevel({ viewportId, window, level }) { // convert to numbers const windowWidthNum = Number(window); const windowCenterNum = Number(level); - const { viewportId } = _getActiveViewportEnabledElement(); - const viewportToolGroupId = toolGroupService.getToolGroupForViewport(viewportId); - - if (toolGroupId && toolGroupId !== viewportToolGroupId) { - return; - } - // get actor from the viewport const renderingEngine = cornerstoneViewportService.getRenderingEngine(); const viewport = renderingEngine.getViewport(viewportId); @@ -265,6 +261,27 @@ function commandsModule({ }); viewport.render(); }, + + toggleViewportColorbar: ({ viewportId, displaySetInstanceUIDs, options = {} }) => { + const hasColorbar = colorbarService.hasColorbar(viewportId); + if (hasColorbar) { + colorbarService.removeColorbar(viewportId); + return; + } + colorbarService.addColorbar(viewportId, displaySetInstanceUIDs, options); + }, + + setWindowLevel(props) { + const { toolGroupId } = props; + const { viewportId } = _getActiveViewportEnabledElement(); + const viewportToolGroupId = toolGroupService.getToolGroupForViewport(viewportId); + + if (toolGroupId && toolGroupId !== viewportToolGroupId) { + return; + } + + actions.setViewportWindowLevel({ ...props, viewportId }); + }, setToolEnabled: ({ toolName, toggle }) => { const { viewports } = viewportGridService.getState(); @@ -514,18 +531,51 @@ function commandsModule({ cstUtils.scroll(viewport, options); }, - setViewportColormap: ({ viewportId, displaySetInstanceUID, colormap, immediate = false }) => { + setViewportColormap: ({ + viewportId, + displaySetInstanceUID, + colormap, + opacity = 1, + immediate = false, + }) => { const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); const actorEntries = viewport.getActors(); + let hpOpacity; + // Retrieve active protocol's viewport match details + const { viewportMatchDetails } = hangingProtocolService.getActiveProtocol(); + // Get display set options for the specified viewport ID + const displaySetsInfo = viewportMatchDetails.get(viewportId)?.displaySetsInfo; - const actorEntry = actorEntries.find(actorEntry => { - return actorEntry.uid.includes(displaySetInstanceUID); - }); + if (displaySetsInfo) { + // Find the display set that matches the given UID + const matchingDisplaySet = displaySetsInfo.find( + displaySet => displaySet.displaySetInstanceUID === displaySetInstanceUID + ); + // If a matching display set is found, update the opacity with its value + hpOpacity = matchingDisplaySet?.displaySetOptions?.options?.colormap?.opacity; + } - const { actor: volumeActor, uid: volumeId } = actorEntry; + // HP takes priority over the default opacity + colormap = { ...colormap, opacity: hpOpacity || opacity }; - viewport.setProperties({ colormap, volumeActor }, volumeId); + const setViewportProperties = (viewport, uid) => { + const actorEntry = actorEntries.find(entry => entry.uid.includes(uid)); + const { actor: volumeActor, uid: volumeId } = actorEntry; + viewport.setProperties({ colormap, volumeActor }, volumeId); + }; + + if (viewport instanceof StackViewport) { + setViewportProperties(viewport, viewportId); + } + + if (viewport instanceof VolumeViewport) { + if (!displaySetInstanceUID) { + const { viewports } = viewportGridService.getState(); + displaySetInstanceUID = viewports.get(viewportId)?.displaySetInstanceUIDs[0]; + } + setViewportProperties(viewport, displaySetInstanceUID); + } if (immediate) { viewport.render(); @@ -608,6 +658,107 @@ function commandsModule({ } }); }, + + setViewportPreset: ({ viewportId, preset }) => { + const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); + if (!viewport) { + return; + } + viewport.setProperties({ + preset, + }); + viewport.render(); + }, + + /** + * Sets the volume quality for a given viewport. + * @param {string} viewportId - The ID of the viewport to set the volume quality. + * @param {number} volumeQuality - The desired quality level of the volume rendering. + */ + + setVolumeRenderingQulaity: ({ viewportId, volumeQuality }) => { + const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); + const { actor } = viewport.getActors()[0]; + const mapper = actor.getMapper(); + const image = mapper.getInputData(); + const dims = image.getDimensions(); + const spacing = image.getSpacing(); + const spatialDiagonal = vec3.length( + vec3.fromValues(dims[0] * spacing[0], dims[1] * spacing[1], dims[2] * spacing[2]) + ); + + let sampleDistance = spacing.reduce((a, b) => a + b) / 3.0; + sampleDistance /= volumeQuality > 1 ? 0.5 * volumeQuality ** 2 : 1.0; + const samplesPerRay = spatialDiagonal / sampleDistance + 1; + mapper.setMaximumSamplesPerRay(samplesPerRay); + mapper.setSampleDistance(sampleDistance); + viewport.render(); + }, + + /** + * Shifts opacity points for a given viewport id. + * @param {string} viewportId - The ID of the viewport to set the mapping range. + * @param {number} shift - The shift value to shift the points by. + */ + shiftVolumeOpacityPoints: ({ viewportId, shift }) => { + const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); + const { actor } = viewport.getActors()[0]; + const ofun = actor.getProperty().getScalarOpacity(0); + + const opacityPointValues = []; // Array to hold values + // Gather Existing Values + const size = ofun.getSize(); + for (let pointIdx = 0; pointIdx < size; pointIdx++) { + const opacityPointValue = [0, 0, 0, 0]; + ofun.getNodeValue(pointIdx, opacityPointValue); + // opacityPointValue now holds [xLocation, opacity, midpoint, sharpness] + opacityPointValues.push(opacityPointValue); + } + // Add offset + opacityPointValues.forEach(opacityPointValue => { + opacityPointValue[0] += shift; // Change the location value + }); + // Set new values + ofun.removeAllPoints(); + opacityPointValues.forEach(opacityPointValue => { + ofun.addPoint(...opacityPointValue); + }); + viewport.render(); + }, + + /** + * Sets the volume lighting settings for a given viewport. + * @param {string} viewportId - The ID of the viewport to set the lighting settings. + * @param {Object} options - The lighting settings to be set. + * @param {boolean} options.shade - The shade setting for the lighting. + * @param {number} options.ambient - The ambient setting for the lighting. + * @param {number} options.diffuse - The diffuse setting for the lighting. + * @param {number} options.specular - The specular setting for the lighting. + **/ + + setVolumeLighting: ({ viewportId, options }) => { + const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); + const { actor } = viewport.getActors()[0]; + const property = actor.getProperty(); + + if (options.shade !== undefined) { + property.setShade(options.shade); + } + + if (options.ambient !== undefined) { + property.setAmbient(options.ambient); + } + + if (options.diffuse !== undefined) { + property.setDiffuse(options.diffuse); + } + + if (options.specular !== undefined) { + property.setSpecular(options.specular); + } + + viewport.render(); + }, resetCrosshairs: ({ viewportId }) => { const crosshairInstances = []; @@ -650,6 +801,11 @@ function commandsModule({ }, getNearbyAnnotation: { commandFn: actions.getNearbyAnnotation, + storeContexts: [], + options: {}, + }, + toggleViewportColorbar: { + commandFn: actions.toggleViewportColorbar, }, deleteMeasurement: { commandFn: actions.deleteMeasurement, @@ -660,6 +816,9 @@ function commandsModule({ updateMeasurement: { commandFn: actions.updateMeasurement, }, + setViewportWindowLevel: { + commandFn: actions.setViewportWindowLevel, + }, setWindowLevel: { commandFn: actions.setWindowLevel, }, @@ -754,6 +913,18 @@ function commandsModule({ attachProtocolViewportDataListener: { commandFn: actions.attachProtocolViewportDataListener, }, + setViewportPreset: { + commandFn: actions.setViewportPreset, + }, + setVolumeRenderingQulaity: { + commandFn: actions.setVolumeRenderingQulaity, + }, + shiftVolumeOpacityPoints: { + commandFn: actions.shiftVolumeOpacityPoints, + }, + setVolumeLighting: { + commandFn: actions.setVolumeLighting, + }, resetCrosshairs: { commandFn: actions.resetCrosshairs, }, diff --git a/extensions/cornerstone/src/components/OHIFViewportActionCorners.tsx b/extensions/cornerstone/src/components/OHIFViewportActionCorners.tsx new file mode 100644 index 000000000..3e7380972 --- /dev/null +++ b/extensions/cornerstone/src/components/OHIFViewportActionCorners.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { useViewportActionCornersContext } from '../contextProviders/ViewportActionCornersProvider'; +import { ViewportActionCorners } from '@ohif/ui'; + +export type OHIFViewportActionCornersProps = { + viewportId: string; +}; + +function OHIFViewportActionCorners({ viewportId }: OHIFViewportActionCornersProps) { + const [viewportActionCornersState] = useViewportActionCornersContext(); + + if (!viewportActionCornersState[viewportId]) { + return null; + } + + return ( + + ); +} + +export default OHIFViewportActionCorners; diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/Colorbar.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/Colorbar.tsx new file mode 100644 index 000000000..e4c2b19cc --- /dev/null +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/Colorbar.tsx @@ -0,0 +1,114 @@ +import React, { ReactElement, useCallback, useEffect, useState } from 'react'; +import { SwitchButton } from '@ohif/ui'; +import { StackViewport, VolumeViewport } from '@cornerstonejs/core'; +import { ColorbarProps } from '../../types/Colorbar'; +import { utilities } from '@cornerstonejs/core'; + +export function setViewportColorbar( + viewportId, + displaySets, + commandsManager, + serviceManager, + colorbarOptions +) { + const { cornerstoneViewportService } = serviceManager.services; + const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); + + const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId); + const backgroundColor = viewportInfo.getViewportOptions().background; + const isLight = backgroundColor ? utilities.isEqual(backgroundColor, [1, 1, 1]) : false; + + if (isLight) { + colorbarOptions.ticks = { + position: 'left', + style: { + font: '12px Arial', + color: '#000000', + maxNumTicks: 8, + tickSize: 5, + tickWidth: 1, + labelMargin: 3, + }, + }; + } + + const displaySetInstanceUIDs = []; + + if (viewport instanceof StackViewport) { + displaySetInstanceUIDs.push(viewportId); + } + + if (viewport instanceof VolumeViewport) { + displaySets.forEach(ds => { + displaySetInstanceUIDs.push(ds.displaySetInstanceUID); + }); + } + + commandsManager.run({ + commandName: 'toggleViewportColorbar', + commandOptions: { + viewportId, + options: colorbarOptions, + displaySetInstanceUIDs, + }, + context: 'CORNERSTONE', + }); +} + +export function Colorbar({ + viewportId, + displaySets, + commandsManager, + serviceManager, + colorbarProperties, +}: ColorbarProps): ReactElement { + const { colorbarService } = serviceManager.services; + const { + width: colorbarWidth, + colorbarTickPosition, + colorbarContainerPosition, + colormaps, + colorbarInitialColormap, + } = colorbarProperties; + const [showColorbar, setShowColorbar] = useState(colorbarService.hasColorbar(viewportId)); + + const onSetColorbar = useCallback(() => { + setViewportColorbar(viewportId, displaySets, commandsManager, serviceManager, { + viewportId, + colormaps, + ticks: { + position: colorbarTickPosition, + }, + width: colorbarWidth, + position: colorbarContainerPosition, + activeColormapName: colorbarInitialColormap, + }); + }, [commandsManager]); + + useEffect(() => { + const updateColorbarState = () => { + setShowColorbar(colorbarService.hasColorbar(viewportId)); + }; + + const { unsubscribe } = colorbarService.subscribe( + colorbarService.EVENTS.STATE_CHANGED, + updateColorbarState + ); + + return () => { + unsubscribe(); + }; + }, [viewportId]); + + return ( +
+ { + onSetColorbar(); + }} + /> +
+ ); +} diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/Colormap.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/Colormap.tsx new file mode 100644 index 000000000..335e54456 --- /dev/null +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/Colormap.tsx @@ -0,0 +1,153 @@ +import React, { ReactElement, useCallback, useEffect, useRef, useState, useMemo } from 'react'; +import { AllInOneMenu, ButtonGroup, SwitchButton } from '@ohif/ui'; +import { StackViewport } from '@cornerstonejs/core'; +import { ColormapProps } from '../../types/Colormap'; + +export function Colormap({ + colormaps, + viewportId, + displaySets, + commandsManager, + serviceManager, +}: ColormapProps): ReactElement { + const { cornerstoneViewportService } = serviceManager.services; + + const [activeDisplaySet, setActiveDisplaySet] = useState(displaySets[0]); + + const [showPreview, setShowPreview] = useState(false); + const [prePreviewColormap, setPrePreviewColormap] = useState(null); + + const showPreviewRef = useRef(showPreview); + showPreviewRef.current = showPreview; + const prePreviewColormapRef = useRef(prePreviewColormap); + prePreviewColormapRef.current = prePreviewColormap; + const activeDisplaySetRef = useRef(activeDisplaySet); + activeDisplaySetRef.current = activeDisplaySet; + + const onSetColorLUT = useCallback( + props => { + // TODO: Better way to check if it's a fusion + const oneOpacityColormaps = ['Grayscale', 'X Ray']; + const opacity = + displaySets.length > 1 && !oneOpacityColormaps.includes(props.colormap.name) ? 0.5 : 1; + commandsManager.run({ + commandName: 'setViewportColormap', + commandOptions: { + ...props, + opacity, + immediate: true, + }, + context: 'CORNERSTONE', + }); + }, + [commandsManager] + ); + + const getViewportColormap = (viewportId, displaySet) => { + const { displaySetInstanceUID } = displaySet; + const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); + if (viewport instanceof StackViewport) { + const { colormap } = viewport.getProperties(); + if (!colormap) { + return colormaps.find(c => c.Name === 'Grayscale') || colormaps[0]; + } + return colormap; + } + const actorEntries = viewport.getActors(); + const actorEntry = actorEntries.find(entry => entry.uid.includes(displaySetInstanceUID)); + const { colormap } = viewport.getProperties(actorEntry.uid); + if (!colormap) { + return colormaps.find(c => c.Name === 'Grayscale') || colormaps[0]; + } + return colormap; + }; + + const buttons = useMemo(() => { + return displaySets.map((displaySet, index) => ({ + children: displaySet.Modality, + key: index, + style: { + minWidth: `calc(100% / ${displaySets.length})`, + }, + })); + }, [displaySets]); + + useEffect(() => { + setActiveDisplaySet(displaySets[displaySets.length - 1]); + }, [displaySets]); + + return ( + <> + {buttons.length > 1 && ( +
+ { + setActiveDisplaySet(displaySets[index]); + setPrePreviewColormap(null); + }} + activeIndex={ + displaySets.findIndex( + ds => ds.displaySetInstanceUID === activeDisplaySetRef.current.displaySetInstanceUID + ) || 1 + } + className="w-[70%] text-[10px]" + > + {buttons.map(({ children, key, style }) => ( +
+ {children} +
+ ))} +
+
+ )} +
+ { + setShowPreview(checked); + }} + /> +
+ + + {colormaps.map((colormap, index) => ( + { + onSetColorLUT({ + viewportId, + colormap, + displaySetInstanceUID: activeDisplaySetRef.current.displaySetInstanceUID, + }); + setPrePreviewColormap(null); + }} + onMouseEnter={() => { + if (showPreviewRef.current) { + setPrePreviewColormap(getViewportColormap(viewportId, activeDisplaySetRef.current)); + onSetColorLUT({ + viewportId, + colormap, + displaySetInstanceUID: activeDisplaySetRef.current.displaySetInstanceUID, + }); + } + }} + onMouseLeave={() => { + if (showPreviewRef.current && prePreviewColormapRef.current) { + onSetColorLUT({ + viewportId, + colormap: prePreviewColormapRef.current, + displaySetInstanceUID: activeDisplaySetRef.current.displaySetInstanceUID, + }); + } + }} + > + ))} + + + ); +} diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeLighting.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeLighting.tsx new file mode 100644 index 000000000..80b6452c6 --- /dev/null +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeLighting.tsx @@ -0,0 +1,118 @@ +import React, { ReactElement, useState, useEffect, useCallback } from 'react'; +import { VolumeLightingProps } from '../../types/ViewportPresets'; + +export function VolumeLighting({ + serviceManager, + commandsManager, + viewportId, +}: VolumeLightingProps): ReactElement { + const { cornerstoneViewportService } = serviceManager.services; + const [ambient, setAmbient] = useState(null); + const [diffuse, setDiffuse] = useState(null); + const [specular, setSpecular] = useState(null); + + const onAmbientChange = useCallback(() => { + commandsManager.runCommand('setVolumeLighting', { viewportId, options: { ambient } }); + }, [ambient, commandsManager, viewportId]); + + const onDiffuseChange = useCallback(() => { + commandsManager.runCommand('setVolumeLighting', { viewportId, options: { diffuse } }); + }, [diffuse, commandsManager, viewportId]); + + const onSpecularChange = useCallback(() => { + commandsManager.runCommand('setVolumeLighting', { viewportId, options: { specular } }); + }, [specular, commandsManager, viewportId]); + + const calculateBackground = value => { + const percentage = ((value - 0) / (1 - 0)) * 100; + return `linear-gradient(to right, #5acce6 0%, #5acce6 ${percentage}%, #3a3f99 ${percentage}%, #3a3f99 100%)`; + }; + + useEffect(() => { + const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); + const { actor } = viewport.getActors()[0]; + const ambient = actor.getProperty().getAmbient(); + const diffuse = actor.getProperty().getDiffuse(); + const specular = actor.getProperty().getSpecular(); + setAmbient(ambient); + setDiffuse(diffuse); + setSpecular(specular); + }, [viewportId, cornerstoneViewportService]); + return ( + <> +
+ + {ambient !== null && ( + { + setAmbient(e.target.value); + onAmbientChange(); + }} + id="ambient" + max={1} + min={0} + type="range" + step={0.1} + style={{ background: calculateBackground(ambient) }} + /> + )} +
+
+ + {diffuse !== null && ( + { + setDiffuse(e.target.value); + onDiffuseChange(); + }} + id="diffuse" + max={1} + min={0} + type="range" + step={0.1} + style={{ background: calculateBackground(diffuse) }} + /> + )} +
+ +
+ + {specular !== null && ( + { + setSpecular(e.target.value); + onSpecularChange(); + }} + id="specular" + max={1} + min={0} + type="range" + step={0.1} + style={{ background: calculateBackground(specular) }} + /> + )} +
+ + ); +} diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingOptions.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingOptions.tsx new file mode 100644 index 000000000..a75f0bd52 --- /dev/null +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingOptions.tsx @@ -0,0 +1,46 @@ +import React, { ReactElement } from 'react'; +import { AllInOneMenu } from '@ohif/ui'; +import { VolumeRenderingOptionsProps } from '../../types/ViewportPresets'; +import { VolumeRenderingQuality } from './VolumeRenderingQuality'; +import { VolumeShift } from './VolumeShift'; +import { VolumeLighting } from './VolumeLighting'; +import { VolumeShade } from './VolumeShade'; +export function VolumeRenderingOptions({ + viewportId, + commandsManager, + volumeRenderingQualityRange, + serviceManager, +}: VolumeRenderingOptionsProps): ReactElement { + return ( + + + + +
+
LIGHTING
+
+ +
+ +
+ +
+ ); +} diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingPresets.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingPresets.tsx new file mode 100644 index 000000000..d288a0fbc --- /dev/null +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingPresets.tsx @@ -0,0 +1,38 @@ +import { AllInOneMenu, Icon } from '@ohif/ui'; +import React, { ReactElement } from 'react'; +import { VolumeRenderingPresetsProps } from '../../types/ViewportPresets'; +import { VolumeRenderingPresetsContent } from './VolumeRenderingPresetsContent'; + +export function VolumeRenderingPresets({ + viewportId, + serviceManager, + commandsManager, + volumeRenderingPresets, +}: VolumeRenderingPresetsProps): ReactElement { + const { uiModalService } = serviceManager.services; + + const onClickPresets = () => { + uiModalService.show({ + content: VolumeRenderingPresetsContent, + title: 'Rendering Presets', + movable: true, + contentProps: { + onClose: uiModalService.hide, + presets: volumeRenderingPresets, + viewportId, + commandsManager, + }, + containerDimensions: 'h-[543px] w-[460px]', + contentDimensions: 'h-[493px] w-[460px] pl-[12px]', + }); + }; + + return ( + } + rightIcon={} + onClick={onClickPresets} + /> + ); +} diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingPresetsContent.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingPresetsContent.tsx new file mode 100644 index 000000000..07c9abcc9 --- /dev/null +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingPresetsContent.tsx @@ -0,0 +1,95 @@ +import { Icon } from '@ohif/ui'; +import { ButtonEnums } from '@ohif/ui'; +import React, { ReactElement, useState, useCallback } from 'react'; +import { Button, InputFilterText } from '@ohif/ui'; +import { ViewportPreset, VolumeRenderingPresetsContentProps } from '../../types/ViewportPresets'; + +export function VolumeRenderingPresetsContent({ + presets, + viewportId, + commandsManager, + onClose, +}: VolumeRenderingPresetsContentProps): ReactElement { + const [filteredPresets, setFilteredPresets] = useState(presets); + const [searchValue, setSearchValue] = useState(''); + const [selectedPreset, setSelectedPreset] = useState(null); + + const handleSearchChange = useCallback( + (value: string) => { + setSearchValue(value); + const filtered = value + ? presets.filter(preset => preset.name.toLowerCase().includes(value.toLowerCase())) + : presets; + setFilteredPresets(filtered); + }, + [presets] + ); + + const handleApply = useCallback( + props => { + commandsManager.runCommand('setViewportPreset', { + ...props, + }); + }, + [commandsManager] + ); + + const formatLabel = (label: string, maxChars: number) => { + return label.length > maxChars ? `${label.slice(0, maxChars)}...` : label; + }; + + return ( +
+
+
+
+ +
+
+
+
+ {filteredPresets.map((preset, index) => ( +
{ + setSelectedPreset(preset); + handleApply({ preset: preset.name, viewportId }); + }} + > + + +
+ ))} +
+
+
+
+
+ +
+
+
+ ); +} diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingQuality.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingQuality.tsx new file mode 100644 index 000000000..d1940a196 --- /dev/null +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingQuality.tsx @@ -0,0 +1,69 @@ +import React, { ReactElement, useCallback, useState, useEffect } from 'react'; +import { VolumeRenderingQualityProps } from '../../types/ViewportPresets'; + +export function VolumeRenderingQuality({ + volumeRenderingQualityRange, + commandsManager, + serviceManager, + viewportId, +}: VolumeRenderingQualityProps): ReactElement { + const { cornerstoneViewportService } = serviceManager.services; + const { min, max, step } = volumeRenderingQualityRange; + const [quality, setQuality] = useState(null); + + const onChange = useCallback( + (value: number) => { + commandsManager.runCommand('setVolumeRenderingQulaity', { + viewportId, + volumeQuality: value, + }); + setQuality(value); + }, + [commandsManager, viewportId] + ); + + const calculateBackground = value => { + const percentage = ((value - 0) / (1 - 0)) * 100; + return `linear-gradient(to right, #5acce6 0%, #5acce6 ${percentage}%, #3a3f99 ${percentage}%, #3a3f99 100%)`; + }; + + useEffect(() => { + const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); + const { actor } = viewport.getActors()[0]; + const mapper = actor.getMapper(); + const image = mapper.getInputData(); + const spacing = image.getSpacing(); + const sampleDistance = mapper.getSampleDistance(); + const averageSpacing = spacing.reduce((a, b) => a + b) / 3.0; + if (sampleDistance === averageSpacing) { + setQuality(1); + } else { + setQuality(Math.sqrt(averageSpacing / (sampleDistance * 0.5))); + } + }, [cornerstoneViewportService, viewportId]); + return ( + <> +
+ + {quality !== null && ( + onChange(parseInt(e.target.value, 10))} + style={{ background: calculateBackground((quality - min) / (max - min)) }} + /> + )} +
+ + ); +} diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShade.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShade.tsx new file mode 100644 index 000000000..319158dab --- /dev/null +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShade.tsx @@ -0,0 +1,39 @@ +import React, { ReactElement, useCallback, useEffect, useState } from 'react'; +import { SwitchButton } from '@ohif/ui'; +import { VolumeShadeProps } from '../../types/ViewportPresets'; + +export function VolumeShade({ + commandsManager, + viewportId, + serviceManager, +}: VolumeShadeProps): ReactElement { + const { cornerstoneViewportService } = serviceManager.services; + const [shade, setShade] = useState(true); + const [key, setKey] = useState(0); + + const onShadeChange = useCallback( + (checked: boolean) => { + commandsManager.runCommand('setVolumeLighting', { viewportId, options: { shade: checked } }); + }, + [commandsManager, viewportId] + ); + useEffect(() => { + const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); + const { actor } = viewport.getActors()[0]; + const shade = actor.getProperty().getShade(); + setShade(shade); + setKey(key + 1); + }, [viewportId, cornerstoneViewportService]); + + return ( + { + setShade(!shade); + onShadeChange(!shade); + }} + /> + ); +} diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShift.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShift.tsx new file mode 100644 index 000000000..6ad9eb9d3 --- /dev/null +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeShift.tsx @@ -0,0 +1,91 @@ +import React, { ReactElement, useCallback, useEffect, useState, useRef } from 'react'; +import { VolumeShiftProps } from '../../types/ViewportPresets'; + +export function VolumeShift({ + viewportId, + commandsManager, + serviceManager, +}: VolumeShiftProps): ReactElement { + const { cornerstoneViewportService } = serviceManager.services; + const [minShift, setMinShift] = useState(null); + const [maxShift, setMaxShift] = useState(null); + const [shift, setShift] = useState( + cornerstoneViewportService.getCornerstoneViewport(viewportId)?.shiftedBy || 0 + ); + const [step, setStep] = useState(null); + const [isBlocking, setIsBlocking] = useState(false); + + const prevShiftRef = useRef(shift); + + const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); + const { actor } = viewport.getActors()[0]; + const ofun = actor.getProperty().getScalarOpacity(0); + + useEffect(() => { + if (isBlocking) { + return; + } + const range = ofun.getRange(); + + const transferFunctionWidth = range[1] - range[0]; + + const minShift = -transferFunctionWidth; + const maxShift = transferFunctionWidth; + + setMinShift(minShift); + setMaxShift(maxShift); + setStep(Math.pow(10, Math.floor(Math.log10(transferFunctionWidth / 500)))); + }, [cornerstoneViewportService, viewportId, actor, ofun, isBlocking]); + + const onChangeRange = useCallback( + newShift => { + const shiftDifference = newShift - prevShiftRef.current; + prevShiftRef.current = newShift; + viewport.shiftedBy = newShift; + commandsManager.runCommand('shiftVolumeOpacityPoints', { + viewportId, + shift: shiftDifference, + }); + }, + [commandsManager, viewportId, viewport] + ); + + const calculateBackground = value => { + const percentage = ((value - 0) / (1 - 0)) * 100; + return `linear-gradient(to right, #5acce6 0%, #5acce6 ${percentage}%, #3a3f99 ${percentage}%, #3a3f99 100%)`; + }; + + return ( + <> +
+ + {step !== null && ( + { + const shiftValue = parseInt(e.target.value, 10); + setShift(shiftValue); + onChangeRange(shiftValue); + }} + id="shift" + onMouseDown={() => setIsBlocking(true)} + onMouseUp={() => setIsBlocking(false)} + max={maxShift} + min={minShift} + type="range" + step={step} + style={{ + background: calculateBackground((shift - minShift) / (maxShift - minShift)), + }} + /> + )} +
+ + ); +} diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/WindowLevel.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/WindowLevel.tsx new file mode 100644 index 000000000..44b75bf93 --- /dev/null +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/WindowLevel.tsx @@ -0,0 +1,48 @@ +import React, { ReactElement, useCallback } from 'react'; +import { AllInOneMenu } from '@ohif/ui'; +import { WindowLevelPreset } from '../../types/WindowLevel'; +import { CommandsManager } from '@ohif/core'; +import { useTranslation } from 'react-i18next'; + +export type WindowLevelProps = { + viewportId: string; + presets: Record>; + commandsManager: CommandsManager; +}; + +export function WindowLevel({ + viewportId, + commandsManager, + presets, +}: WindowLevelProps): ReactElement { + const { t } = useTranslation('WindowLevelActionMenu'); + + const onSetWindowLevel = useCallback( + props => { + commandsManager.run({ + commandName: 'setViewportWindowLevel', + commandOptions: { + ...props, + }, + context: 'CORNERSTONE', + }); + }, + [commandsManager] + ); + + return ( + + + {t('Modality Presets', { modality: Object.keys(presets)[0] })} + + {Object.values(presets)[0].map((preset, index) => ( + onSetWindowLevel({ ...preset, viewportId })} + > + ))} + + ); +} diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/WindowLevelActionMenu.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/WindowLevelActionMenu.tsx new file mode 100644 index 000000000..b4db9fd21 --- /dev/null +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/WindowLevelActionMenu.tsx @@ -0,0 +1,205 @@ +import React, { ReactElement, useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import classNames from 'classnames'; +import { AllInOneMenu, useViewportGrid } from '@ohif/ui'; +import { CommandsManager, ServicesManager } from '@ohif/core'; +import { Colormap } from './Colormap'; +import { Colorbar } from './Colorbar'; +import { setViewportColorbar } from './Colorbar'; +import { WindowLevelPreset } from '../../types/WindowLevel'; +import { ColorbarProperties } from '../../types/Colorbar'; +import { VolumeRenderingQualityRange } from '../../types/ViewportPresets'; +import { WindowLevel } from './WindowLevel'; +import { VolumeRenderingPresets } from './VolumeRenderingPresets'; +import { VolumeRenderingOptions } from './VolumeRenderingOptions'; +import { ViewportPreset } from '../../types/ViewportPresets'; +import { VolumeViewport3D } from '@cornerstonejs/core'; +import { utilities } from '@cornerstonejs/core'; + +export type WindowLevelActionMenuProps = { + viewportId: string; + element: HTMLElement; + presets: Record>; + verticalDirection: AllInOneMenu.VerticalDirection; + horizontalDirection: AllInOneMenu.HorizontalDirection; + commandsManager: CommandsManager; + serviceManager: ServicesManager; + colorbarProperties: ColorbarProperties; + displaySets: Array; + volumeRenderingPresets: Array; + volumeRenderingQualityRange: VolumeRenderingQualityRange; +}; + +export function WindowLevelActionMenu({ + viewportId, + element, + presets, + verticalDirection, + horizontalDirection, + commandsManager, + serviceManager, + colorbarProperties, + displaySets, + volumeRenderingPresets, + volumeRenderingQualityRange, +}: WindowLevelActionMenuProps): ReactElement { + const { + colormaps, + colorbarContainerPosition, + colorbarInitialColormap, + colorbarTickPosition, + width: colorbarWidth, + } = colorbarProperties; + const { colorbarService, cornerstoneViewportService } = serviceManager.services; + const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId); + const backgroundColor = viewportInfo.getViewportOptions().background; + const isLight = backgroundColor ? utilities.isEqual(backgroundColor, [1, 1, 1]) : false; + + const nonImageModalities = ['SR', 'SEG', 'SM', 'RTSTRUCT', 'RTPLAN', 'RTDOSE']; + + const { t } = useTranslation('WindowLevelActionMenu'); + + const [viewportGrid] = useViewportGrid(); + const { activeViewportId } = viewportGrid; + + const [vpHeight, setVpHeight] = useState(element?.clientHeight); + const [menuKey, setMenuKey] = useState(0); + const [is3DVolume, setIs3DVolume] = useState(false); + + const onSetColorbar = useCallback(() => { + setViewportColorbar(viewportId, displaySets, commandsManager, serviceManager, { + colormaps, + ticks: { + position: colorbarTickPosition, + }, + width: colorbarWidth, + position: colorbarContainerPosition, + activeColormapName: colorbarInitialColormap, + }); + }, [commandsManager]); + + useEffect(() => { + const newVpHeight = element?.clientHeight; + if (vpHeight !== newVpHeight) { + setVpHeight(newVpHeight); + } + }, [element, vpHeight]); + + useEffect(() => { + if (!colorbarService.hasColorbar(viewportId)) { + return; + } + window.setTimeout(() => { + colorbarService.removeColorbar(viewportId); + onSetColorbar(); + }, 0); + }, [viewportId]); + + useEffect(() => { + if (colorbarService.hasColorbar(viewportId)) { + colorbarService.removeColorbar(viewportId); + } + }, [displaySets]); + + useEffect(() => { + setMenuKey(menuKey + 1); + const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); + if (viewport instanceof VolumeViewport3D) { + setIs3DVolume(true); + } else { + setIs3DVolume(false); + } + }, [ + displaySets, + viewportId, + presets, + volumeRenderingQualityRange, + volumeRenderingPresets, + colorbarProperties, + activeViewportId, + viewportGrid, + ]); + + return ( + { + setVpHeight(element.clientHeight); + }} + menuKey={menuKey} + > + + {!is3DVolume && ( + !nonImageModalities.includes(ds.Modality))} + commandsManager={commandsManager} + serviceManager={serviceManager} + colorbarProperties={colorbarProperties} + /> + )} + + {colormaps && !is3DVolume && ( + + !nonImageModalities.includes(ds.Modality))} + commandsManager={commandsManager} + serviceManager={serviceManager} + /> + + )} + + {presets && !is3DVolume && ( + + + + )} + + {volumeRenderingPresets && is3DVolume && ( + + )} + + {volumeRenderingQualityRange && is3DVolume && ( + + + + )} + + + ); +} diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/defaultWindowLevelPresets.ts b/extensions/cornerstone/src/components/WindowLevelActionMenu/defaultWindowLevelPresets.ts new file mode 100644 index 000000000..f12a7530b --- /dev/null +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/defaultWindowLevelPresets.ts @@ -0,0 +1,23 @@ +// The following are the default window level presets and can be further +// configured via the customization service. +const defaultWindowLevelPresets = { + CT: [ + { description: 'Soft tissue', window: '400', level: '40' }, + { description: 'Lung', window: '1500', level: '-600' }, + { description: 'Liver', window: '150', level: '90' }, + { description: 'Bone', window: '2500', level: '480' }, + { description: 'Brain', window: '80', level: '40' }, + ], + + PT: [ + { description: 'Default', window: '5', level: '2.5' }, + { description: 'SUV', window: '0', level: '3' }, + { description: 'SUV', window: '0', level: '5' }, + { description: 'SUV', window: '0', level: '7' }, + { description: 'SUV', window: '0', level: '8' }, + { description: 'SUV', window: '0', level: '10' }, + { description: 'SUV', window: '0', level: '15' }, + ], +}; + +export default defaultWindowLevelPresets; diff --git a/extensions/cornerstone/src/components/WindowLevelActionMenu/getWindowLevelActionMenu.tsx b/extensions/cornerstone/src/components/WindowLevelActionMenu/getWindowLevelActionMenu.tsx new file mode 100644 index 000000000..7a31c5a7a --- /dev/null +++ b/extensions/cornerstone/src/components/WindowLevelActionMenu/getWindowLevelActionMenu.tsx @@ -0,0 +1,44 @@ +import React, { ReactNode } from 'react'; +import { WindowLevelActionMenu } from './WindowLevelActionMenu'; + +export function getWindowLevelActionMenu({ + viewportId, + element, + displaySets, + servicesManager, + commandsManager, + verticalDirection, + horizontalDirection, +}): ReactNode { + const { customizationService } = servicesManager.services; + + const { presets } = customizationService.get('cornerstone.windowLevelPresets'); + const colorbarProperties = customizationService.get('cornerstone.colorbar'); + const { volumeRenderingPresets, volumeRenderingQualityRange } = customizationService.get( + 'cornerstone.3dVolumeRendering' + ); + + const displaySetPresets = displaySets + .filter(displaySet => presets[displaySet.Modality]) + .map(displaySet => { + return { [displaySet.Modality]: presets[displaySet.Modality] }; + }); + + const hasMenu = displaySetPresets.length > 0; + + return hasMenu ? ( + + ) : null; +} diff --git a/extensions/cornerstone/src/contextProviders/ViewportActionCornersProvider.tsx b/extensions/cornerstone/src/contextProviders/ViewportActionCornersProvider.tsx new file mode 100644 index 000000000..37dab07e6 --- /dev/null +++ b/extensions/cornerstone/src/contextProviders/ViewportActionCornersProvider.tsx @@ -0,0 +1,159 @@ +import React, { + createContext, + useCallback, + useContext, + useEffect, + useMemo, + useReducer, +} from 'react'; +import PropTypes from 'prop-types'; + +import { Types, ViewportActionCornersLocations } from '@ohif/ui'; +import ViewportActionCornersService, { + ActionComponentInfo, +} from '../services/ViewportActionCornersService/ViewportActionCornersService'; + +interface StateComponentInfo extends Types.ViewportActionCornersComponentInfo { + indexPriority: number; +} + +type State = Record>>; + +const DEFAULT_STATE: State = { + // default here is the viewportId of the default viewport + default: { + [ViewportActionCornersLocations.topLeft]: [], + [ViewportActionCornersLocations.topRight]: [], + [ViewportActionCornersLocations.bottomLeft]: [], + [ViewportActionCornersLocations.bottomRight]: [], + }, + // [anotherViewportId]: { ..... } +}; + +export const ViewportActionCornersContext = createContext(DEFAULT_STATE); + +export function ViewportActionCornersProvider({ children, service }) { + const viewportActionCornersReducer = (state, action) => { + switch (action.type) { + case 'SET_ACTION_COMPONENT': { + const { viewportId, id, component, location, indexPriority = 0 } = action.payload; + // Get the components at the specified location of the specified viewport. + let locationComponents = state?.[viewportId]?.[location] + ? [...state[viewportId][location]] + : []; + + // If the component (id) already exists at the location specified in the payload, + // then it must be replaced with the component in the payload so first + // remove it from that location. + const deletionIndex = locationComponents.findIndex(component => component.id === id); + if (deletionIndex !== -1) { + locationComponents = [ + ...locationComponents.slice(0, deletionIndex), + ...locationComponents.slice(deletionIndex + 1), + ]; + } + + // Insert the component from the payload but + // do not insert an undefined or null component. + if (component) { + const insertionIndex = locationComponents.findIndex( + component => indexPriority <= component.indexPriority + ); + locationComponents = [ + ...locationComponents.slice(0, insertionIndex), + { + id, + component, + indexPriority, + }, + ...locationComponents.slice(insertionIndex + 1), + ]; + } + + return { + ...state, + ...{ + [viewportId]: { + ...state[viewportId], + [location]: locationComponents, + }, + }, + }; + } + case 'CLEAR_ACTION_COMPONENTS': { + const viewportId = action.payload; + const nextState = { ...state }; + delete nextState[viewportId]; + return nextState; + } + default: + return { ...state }; + } + }; + + const [viewportActionCornersState, dispatch] = useReducer( + viewportActionCornersReducer, + DEFAULT_STATE + ); + + const getState = useCallback(() => { + return viewportActionCornersState; + }, [viewportActionCornersState]); + + const setComponent = useCallback( + (actionComponentInfo: ActionComponentInfo) => { + dispatch({ type: 'SET_ACTION_COMPONENT', payload: actionComponentInfo }); + }, + [dispatch] + ); + + const setComponents = useCallback( + (actionComponentInfos: Array) => { + actionComponentInfos.forEach(actionComponentInfo => + dispatch({ type: 'SET_ACTION_COMPONENT', payload: actionComponentInfo }) + ); + }, + [dispatch] + ); + + const clear = useCallback( + (viewportId: string) => dispatch({ type: 'CLEAR_ACTION_COMPONENTS', payload: viewportId }), + [dispatch] + ); + useEffect(() => { + if (service) { + service.setServiceImplementation({ + getState, + setComponent, + setComponents, + clear, + }); + } + }, [getState, service, setComponent, setComponents]); + + // run many of the calls through the service itself since we want to publish events + const api = { + getState, + setComponent: props => service.setComponent(props), + setComponents: props => service.setComponents(props), + clear: props => service.clear(props), + }; + + const contextValue = useMemo( + () => [viewportActionCornersState, api], + [viewportActionCornersState, api] + ); + + return ( + + {children} + + ); +} + +ViewportActionCornersProvider.propTypes = { + children: PropTypes.node, + service: PropTypes.instanceOf(ViewportActionCornersService).isRequired, +}; + +export const useViewportActionCornersContext = () => useContext(ViewportActionCornersContext); diff --git a/extensions/cornerstone/src/getCustomizationModule.ts b/extensions/cornerstone/src/getCustomizationModule.ts index acb064244..90bf67f6c 100644 --- a/extensions/cornerstone/src/getCustomizationModule.ts +++ b/extensions/cornerstone/src/getCustomizationModule.ts @@ -1,6 +1,12 @@ import { Enums } from '@cornerstonejs/tools'; import { toolNames } from './initCornerstoneTools'; import DicomUpload from './components/DicomUpload/DicomUpload'; +import defaultWindowLevelPresets from './components/WindowLevelActionMenu/defaultWindowLevelPresets'; +import { colormaps } from './utils/colormaps'; +import { CONSTANTS } from '@cornerstonejs/core'; + +const DefaultColormap = 'Grayscale'; +const { VIEWPORT_PRESETS } = CONSTANTS; const tools = { active: [ @@ -37,6 +43,27 @@ function getCustomizationModule() { id: 'cornerstone.overlayViewportTools', tools, }, + { + id: 'cornerstone.windowLevelPresets', + presets: defaultWindowLevelPresets, + }, + { + id: 'cornerstone.colorbar', + width: '16px', + colorbarTickPosition: 'left', + colormaps, + colorbarContainerPosition: 'right', + colorbarInitialColormap: DefaultColormap, + }, + { + id: 'cornerstone.3dVolumeRendering', + volumeRenderingPresets: VIEWPORT_PRESETS, + volumeRenderingQualityRange: { + min: 1, + max: 4, + step: 1, + }, + }, ], }, ]; diff --git a/extensions/cornerstone/src/hps/fourUp.ts b/extensions/cornerstone/src/hps/fourUp.ts index ac7435fb8..69305e6c1 100644 --- a/extensions/cornerstone/src/hps/fourUp.ts +++ b/extensions/cornerstone/src/hps/fourUp.ts @@ -52,6 +52,9 @@ export const fourUp = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -94,6 +97,9 @@ export const fourUp = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -117,6 +123,9 @@ export const fourUp = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, diff --git a/extensions/cornerstone/src/hps/main3D.ts b/extensions/cornerstone/src/hps/main3D.ts index e59437cb3..a00ccc4a7 100644 --- a/extensions/cornerstone/src/hps/main3D.ts +++ b/extensions/cornerstone/src/hps/main3D.ts @@ -97,6 +97,9 @@ export const main3D = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -120,6 +123,9 @@ export const main3D = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -143,6 +149,9 @@ export const main3D = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, diff --git a/extensions/cornerstone/src/hps/mpr.ts b/extensions/cornerstone/src/hps/mpr.ts index 5927af785..ea2219163 100644 --- a/extensions/cornerstone/src/hps/mpr.ts +++ b/extensions/cornerstone/src/hps/mpr.ts @@ -87,6 +87,9 @@ export const mpr: Types.HangingProtocol.Protocol = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -111,6 +114,9 @@ export const mpr: Types.HangingProtocol.Protocol = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -135,6 +141,9 @@ export const mpr: Types.HangingProtocol.Protocol = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, diff --git a/extensions/cornerstone/src/hps/mprAnd3DVolumeViewport.ts b/extensions/cornerstone/src/hps/mprAnd3DVolumeViewport.ts index 120f6fb7e..759ce1849 100644 --- a/extensions/cornerstone/src/hps/mprAnd3DVolumeViewport.ts +++ b/extensions/cornerstone/src/hps/mprAnd3DVolumeViewport.ts @@ -59,6 +59,9 @@ export const mprAnd3DVolumeViewport = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -100,6 +103,9 @@ export const mprAnd3DVolumeViewport = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -123,6 +129,9 @@ export const mprAnd3DVolumeViewport = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, diff --git a/extensions/cornerstone/src/hps/primary3D.ts b/extensions/cornerstone/src/hps/primary3D.ts index 8d92943ae..11054d106 100644 --- a/extensions/cornerstone/src/hps/primary3D.ts +++ b/extensions/cornerstone/src/hps/primary3D.ts @@ -97,6 +97,9 @@ export const primary3D = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -120,6 +123,9 @@ export const primary3D = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -143,6 +149,9 @@ export const primary3D = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, diff --git a/extensions/cornerstone/src/hps/primaryAxial.ts b/extensions/cornerstone/src/hps/primaryAxial.ts index f42b919fa..430dcbf16 100644 --- a/extensions/cornerstone/src/hps/primaryAxial.ts +++ b/extensions/cornerstone/src/hps/primaryAxial.ts @@ -72,6 +72,9 @@ export const primaryAxial = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -95,6 +98,9 @@ export const primaryAxial = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -118,6 +124,9 @@ export const primaryAxial = { id: 'mpr', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, diff --git a/extensions/cornerstone/src/index.tsx b/extensions/cornerstone/src/index.tsx index 808f63afa..6a4fdffc1 100644 --- a/extensions/cornerstone/src/index.tsx +++ b/extensions/cornerstone/src/index.tsx @@ -19,6 +19,7 @@ import SyncGroupService from './services/SyncGroupService'; import SegmentationService from './services/SegmentationService'; import CornerstoneCacheService from './services/CornerstoneCacheService'; import CornerstoneViewportService from './services/ViewportService/CornerstoneViewportService'; +import ColorbarService from './services/ColorbarService'; import * as CornerstoneExtensionTypes from './types'; import { toolNames } from './initCornerstoneTools'; @@ -30,6 +31,8 @@ import { id } from './id'; import { measurementMappingUtils } from './utils/measurementServiceMappings'; import type { PublicViewportOptions } from './services/ViewportService/Viewport'; import ImageOverlayViewerTool from './tools/ImageOverlayViewerTool'; +import ViewportActionCornersService from './services/ViewportActionCornersService/ViewportActionCornersService'; +import { ViewportActionCornersProvider } from './contextProviders/ViewportActionCornersProvider'; const Component = React.lazy(() => { return import(/* webpackPrefetch: true */ './Viewport/OHIFCornerstoneViewport'); @@ -69,13 +72,19 @@ const cornerstoneExtension: Types.Extensions.Extension = { * @param configuration.csToolsConfig - Passed directly to `initCornerstoneTools` */ preRegistration: function (props: Types.Extensions.ExtensionParams): Promise { - const { servicesManager } = props; + const { servicesManager, serviceProvidersManager } = props; servicesManager.registerService(CornerstoneViewportService.REGISTRATION); servicesManager.registerService(ToolGroupService.REGISTRATION); servicesManager.registerService(SyncGroupService.REGISTRATION); servicesManager.registerService(SegmentationService.REGISTRATION); servicesManager.registerService(CornerstoneCacheService.REGISTRATION); + servicesManager.registerService(ViewportActionCornersService.REGISTRATION); + servicesManager.registerService(ColorbarService.REGISTRATION); + serviceProvidersManager.registerProvider( + ViewportActionCornersService.REGISTRATION.name, + ViewportActionCornersProvider + ); return init.call(this, props); }, diff --git a/extensions/cornerstone/src/init.tsx b/extensions/cornerstone/src/init.tsx index 6d7f3ef7a..2ddd64a33 100644 --- a/extensions/cornerstone/src/init.tsx +++ b/extensions/cornerstone/src/init.tsx @@ -29,6 +29,10 @@ import initContextMenu from './initContextMenu'; import initDoubleClick from './initDoubleClick'; import { CornerstoneServices } from './types'; import initViewTiming from './utils/initViewTiming'; +import { utilities } from '@cornerstonejs/core'; +import { colormaps } from './utils/colormaps'; + +const { registerColormap } = utilities.colormap; // TODO: Cypress tests are currently grabbing this from the window? window.cornerstone = cornerstone; @@ -282,10 +286,7 @@ export default async function init({ eventTarget.addEventListener(EVENTS.ELEMENT_DISABLED, elementDisabledHandler.bind(null)); - // viewportGridService.subscribe( - // viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED, - // activeViewportEventListener - // ); + colormaps.forEach(registerColormap); } function CPUModal() { diff --git a/extensions/cornerstone/src/services/ColorbarService/ColorbarService.ts b/extensions/cornerstone/src/services/ColorbarService/ColorbarService.ts new file mode 100644 index 000000000..688abce65 --- /dev/null +++ b/extensions/cornerstone/src/services/ColorbarService/ColorbarService.ts @@ -0,0 +1,267 @@ +import { PubSubService } from '@ohif/core'; +import { RENDERING_ENGINE_ID } from '../ViewportService/constants'; +import { StackViewport, VolumeViewport, getRenderingEngine } from '@cornerstonejs/core'; +import { utilities } from '@cornerstonejs/tools'; +import { ColorbarOptions, ChangeTypes } from '../../types/Colorbar'; +const { ViewportColorbar } = utilities.voi.colorbar; + +export default class ColorbarService extends PubSubService { + static EVENTS = { + STATE_CHANGED: 'event::ColorbarService:stateChanged', + }; + + static defaultStyles = { + position: 'absolute', + boxSizing: 'border-box', + border: 'solid 1px #555', + cursor: 'initial', + }; + + static positionStyles = { + left: { left: '5%' }, + right: { right: '5%' }, + top: { top: '5%' }, + bottom: { bottom: '5%' }, + }; + + static defaultTickStyles = { + position: 'left', + style: { + font: '12px Arial', + color: '#fff', + maxNumTicks: 8, + tickSize: 5, + tickWidth: 1, + labelMargin: 3, + }, + }; + + public static REGISTRATION = { + name: 'colorbarService', + create: () => { + return new ColorbarService(); + }, + }; + colorbars = {}; + + constructor() { + super(ColorbarService.EVENTS); + } + + /** + * Adds a colorbar to a specific viewport identified by `viewportId`, using the provided `displaySetInstanceUIDs` and `options`. + * This method sets up the colorbar, associates it with the viewport, and applies initial configurations based on the provided options. + * + * @param viewportId The identifier for the viewport where the colorbar will be added. + * @param displaySetInstanceUIDs An array of display set instance UIDs to associate with the colorbar. + * @param options Configuration options for the colorbar, including position, colormaps, active colormap name, ticks, and width. + */ + public addColorbar(viewportId, displaySetInstanceUIDs, options = {} as ColorbarOptions) { + const renderingEngine = getRenderingEngine(RENDERING_ENGINE_ID); + const viewport = renderingEngine.getViewport(viewportId); + const { element } = viewport; + const actorEntries = viewport.getActors(); + const { position, width: thickness, activeColormapName, colormaps } = options; + + const numContainers = displaySetInstanceUIDs.length; + + const containers = this.createContainers( + numContainers, + element, + position, + thickness, + viewportId + ); + + displaySetInstanceUIDs.forEach((displaySetInstanceUID, index) => { + const actorEntry = actorEntries.find(entry => entry.uid.includes(displaySetInstanceUID)); + if (!actorEntry) { + return; + } + const { uid: volumeId } = actorEntry; + const properties = viewport?.getProperties(volumeId); + const colormap = properties?.colormap; + // if there's an initial colormap set, and no colormap on the viewport, set it + if (activeColormapName && !colormap) { + this.setViewportColormap( + viewportId, + displaySetInstanceUID, + colormaps[activeColormapName], + true + ); + } + + const colorbarContainer = containers[index]; + + const colorbar = new ViewportColorbar({ + id: `ctColorbar-${viewportId}-${index}`, + element, + colormaps: options.colormaps || {}, + // if there's an existing colormap set, we use it, otherwise we use the activeColormapName, otherwise, grayscale + activeColormapName: colormap?.name || options?.activeColormapName || 'Grayscale', + container: colorbarContainer, + ticks: { + ...ColorbarService.defaultTickStyles, + ...options.ticks, + }, + volumeId: viewport instanceof VolumeViewport ? volumeId : undefined, + }); + if (this.colorbars[viewportId]) { + this.colorbars[viewportId].push({ colorbar, container: colorbarContainer }); + } else { + this.colorbars[viewportId] = [{ colorbar, container: colorbarContainer }]; + } + }); + + this._broadcastEvent(ColorbarService.EVENTS.STATE_CHANGED, { + viewportId, + changeType: ChangeTypes.Added, + }); + } + + /** + * Removes the colorbar associated with a given viewport ID. This involves cleaning up any created DOM elements and internal references. + * + * @param viewportId The identifier for the viewport from which the colorbar will be removed. + */ + public removeColorbar(viewportId) { + const colorbarInfo = this.colorbars[viewportId]; + if (!colorbarInfo) { + return; + } + + colorbarInfo.forEach(({ colorbar, container }) => { + container.parentNode.removeChild(container); + }); + + delete this.colorbars[viewportId]; + + this._broadcastEvent(ColorbarService.EVENTS.STATE_CHANGED, { + viewportId, + changeType: ChangeTypes.Removed, + }); + } + + /** + * Checks whether a colorbar is associated with a given viewport ID. + * + * @param viewportId The identifier for the viewport to check. + * @returns `true` if a colorbar exists for the specified viewport, otherwise `false`. + */ + public hasColorbar(viewportId) { + return this.colorbars[viewportId] ? true : false; + } + + /** + * Retrieves the current state of colorbars, including all active colorbars and their configurations. + * + * @returns An object representing the current state of all colorbars managed by this service. + */ + public getState() { + return this.colorbars; + } + + /** + * Retrieves colorbar information for a specific viewport ID. + * + * @param viewportId The identifier for the viewport to retrieve colorbar information for. + * @returns The colorbar information associated with the specified viewport, if available. + */ + public getViewportColorbar(viewportId) { + return this.colorbars[viewportId]; + } + + /** + * Handles the cleanup and removal of all colorbars from the viewports. This is typically called + * when exiting the mode or context in which the colorbars are used, ensuring that no DOM + * elements or references are left behind. + */ + public onModeExit() { + const viewportIds = Object.keys(this.colorbars); + viewportIds.forEach(viewportId => { + this.removeColorbar(viewportId); + }); + } + + /** + * Sets the colormap for a viewport. This function is used internally to update the colormap the viewport + * + * @param viewportId The identifier of the viewport to update. + * @param displaySetInstanceUID The display set instance UID associated with the viewport. + * @param colormap The colormap object to set on the viewport. + * @param immediate A boolean indicating whether the viewport should be re-rendered immediately after setting the colormap. + */ + private setViewportColormap(viewportId, displaySetInstanceUID, colormap, immediate = false) { + const renderingEngine = getRenderingEngine(RENDERING_ENGINE_ID); + const viewport = renderingEngine.getViewport(viewportId); + const actorEntries = viewport.getActors(); + + const setViewportProperties = (viewport, uid) => { + const actorEntry = actorEntries.find(entry => entry.uid.includes(uid)); + const { actor: volumeActor, uid: volumeId } = actorEntry; + viewport.setProperties({ colormap, volumeActor }, volumeId); + }; + + if (viewport instanceof StackViewport) { + setViewportProperties(viewport, viewportId); + } + + if (viewport instanceof VolumeViewport) { + setViewportProperties(viewport, displaySetInstanceUID); + } + + if (immediate) { + viewport.render(); + } + } + + /** + * Creates the container elements for colorbars based on the specified parameters. This function dynamically + * generates and styles DOM elements to host the colorbars, positioning them according to the specified options. + * + * @param numContainers The number of containers to create, typically corresponding to the number of colorbars. + * @param element The DOM element within which the colorbar containers will be placed. + * @param position The position of the colorbar containers (e.g., 'top', 'bottom', 'left', 'right'). + * @param thickness The thickness of the colorbar containers, affecting their width or height depending on their position. + * @param viewportId The identifier of the viewport for which the containers are being created. + * @returns An array of the created container DOM elements. + */ + private createContainers(numContainers, element, position, thickness, viewportId) { + const containers = []; + const dimensions = { + 1: 50, + 2: 33, + }; + const dimension = dimensions[numContainers] || 50 / numContainers; + + Array.from({ length: numContainers }).forEach((_, i) => { + const colorbarContainer = document.createElement('div'); + colorbarContainer.id = `ctColorbarContainer-${viewportId}-${i + 1}`; + + Object.assign(colorbarContainer.style, ColorbarService.defaultStyles); + + if (['top', 'bottom'].includes(position)) { + Object.assign(colorbarContainer.style, { + width: `${dimension}%`, + height: thickness || '2.5%', + left: `${(i + 1) * dimension}%`, + transform: 'translateX(-50%)', + ...ColorbarService.positionStyles[position], + }); + } else if (['left', 'right'].includes(position)) { + Object.assign(colorbarContainer.style, { + height: `${dimension}%`, + width: thickness || '2.5%', + top: `${(i + 1) * dimension}%`, + transform: 'translateY(-50%)', + ...ColorbarService.positionStyles[position], + }); + } + + element.appendChild(colorbarContainer); + containers.push(colorbarContainer); + }); + + return containers; + } +} diff --git a/extensions/cornerstone/src/services/ColorbarService/index.ts b/extensions/cornerstone/src/services/ColorbarService/index.ts new file mode 100644 index 000000000..32bd65056 --- /dev/null +++ b/extensions/cornerstone/src/services/ColorbarService/index.ts @@ -0,0 +1,2 @@ +import ColorbarService from './ColorbarService'; +export default ColorbarService; diff --git a/extensions/cornerstone/src/services/ViewportActionCornersService/ViewportActionCornersService.ts b/extensions/cornerstone/src/services/ViewportActionCornersService/ViewportActionCornersService.ts new file mode 100644 index 000000000..baf155764 --- /dev/null +++ b/extensions/cornerstone/src/services/ViewportActionCornersService/ViewportActionCornersService.ts @@ -0,0 +1,71 @@ +import { PubSubService } from '@ohif/core'; +import { ViewportActionCornersLocations } from '@ohif/ui'; +import { ReactNode } from 'react'; + +export type ActionComponentInfo = { + viewportId: string; + id: string; + component: ReactNode; + location: ViewportActionCornersLocations; + indexPriority: number; +}; + +class ViewportActionCornersService extends PubSubService { + public static readonly EVENTS = {}; + public static readonly LOCATIONS = ViewportActionCornersLocations; + + public static REGISTRATION = { + name: 'viewportActionCornersService', + altName: 'ViewportActionCornersService', + create: ({ configuration = {} }) => { + return new ViewportActionCornersService(); + }, + }; + + serviceImplementation = {}; + + public LOCATIONS = ViewportActionCornersService.LOCATIONS; + + constructor() { + super(ViewportActionCornersService.EVENTS); + this.serviceImplementation = {}; + } + + public setServiceImplementation({ + getState: getStateImplementation, + setComponent: setComponentImplementation, + setComponents: setComponentsImplementation, + clear: clearImplementation, + }): void { + if (getStateImplementation) { + this.serviceImplementation._getState = getStateImplementation; + } + if (setComponentImplementation) { + this.serviceImplementation._setComponent = setComponentImplementation; + } + if (setComponentsImplementation) { + this.serviceImplementation._setComponents = setComponentsImplementation; + } + if (clearImplementation) { + this.serviceImplementation._clear = clearImplementation; + } + } + + public getState() { + return this.serviceImplementation._getState(); + } + + public setComponent(component: ActionComponentInfo) { + this.serviceImplementation._setComponent(component); + } + + public setComponents(components: Array) { + this.serviceImplementation._setComponents(components); + } + + public clear(viewportId: string) { + this.serviceImplementation._clear(viewportId); + } +} + +export default ViewportActionCornersService; diff --git a/extensions/cornerstone/src/types/Colorbar.ts b/extensions/cornerstone/src/types/Colorbar.ts new file mode 100644 index 000000000..79beb199f --- /dev/null +++ b/extensions/cornerstone/src/types/Colorbar.ts @@ -0,0 +1,32 @@ +import { ColorMapPreset } from './Colormap'; +import { CommandsManager, ServicesManager } from '@ohif/core'; + +export type ColorbarOptions = { + position: string; + colormaps: Array; + activeColormapName: string; + ticks: object; + width: string; +}; + +export type ColorbarProps = { + viewportId: string; + commandsManager: CommandsManager; + serviceManager: ServicesManager; + displaySets: Array; + colorbarProperties: ColorbarProperties; +}; + +export type ColorbarProperties = { + width: string; + colorbarTickPosition: string; + colorbarContainerPosition: string; + colormaps: Array; + colorbarInitialColormap: string; +}; + +export enum ChangeTypes { + Removed = 'removed', + Added = 'added', + Modified = 'modified', +} diff --git a/extensions/cornerstone/src/types/Colormap.ts b/extensions/cornerstone/src/types/Colormap.ts new file mode 100644 index 000000000..d0cf1b22a --- /dev/null +++ b/extensions/cornerstone/src/types/Colormap.ts @@ -0,0 +1,16 @@ +import { CommandsManager, ServicesManager } from '@ohif/core'; + +export type ColorMapPreset = { + ColorSpace; + description: string; + RGBPoints; + Name; +}; + +export type ColormapProps = { + viewportId: string; + commandsManager: CommandsManager; + serviceManager: ServicesManager; + colormaps: Array; + displaySets: Array; +}; diff --git a/extensions/cornerstone/src/types/CornerstoneServices.ts b/extensions/cornerstone/src/types/CornerstoneServices.ts index b7b791ae6..a55b4ab47 100644 --- a/extensions/cornerstone/src/types/CornerstoneServices.ts +++ b/extensions/cornerstone/src/types/CornerstoneServices.ts @@ -4,6 +4,7 @@ import SyncGroupService from '../services/SyncGroupService'; import SegmentationService from '../services/SegmentationService'; import CornerstoneCacheService from '../services/CornerstoneCacheService'; import CornerstoneViewportService from '../services/ViewportService/CornerstoneViewportService'; +import ViewportActionCornersService from '../services/ViewportActionCornersService/ViewportActionCornersService'; interface CornerstoneServices extends Types.Services { cornerstoneViewportService: CornerstoneViewportService; @@ -11,6 +12,7 @@ interface CornerstoneServices extends Types.Services { syncGroupService: SyncGroupService; segmentationService: SegmentationService; cornerstoneCacheService: CornerstoneCacheService; + viewportActionCornersService: ViewportActionCornersService; } export default CornerstoneServices; diff --git a/extensions/cornerstone/src/types/ViewportPresets.ts b/extensions/cornerstone/src/types/ViewportPresets.ts new file mode 100644 index 000000000..070a6bbde --- /dev/null +++ b/extensions/cornerstone/src/types/ViewportPresets.ts @@ -0,0 +1,66 @@ +import { ServicesManager, CommandsManager } from '@ohif/core'; + +export type ViewportPreset = { + name: string; + gradientOpacity: string; + specularPower: string; + scalarOpacity: string; + specular: string; + shade: string; + ambient: string; + colorTransfer: string; + diffuse: string; + interpolation: string; +}; + +export type VolumeRenderingPresetsProps = { + viewportId: string; + serviceManager: ServicesManager; + commandsManager: CommandsManager; + volumeRenderingPresets: ViewportPreset[]; +}; + +export type VolumeRenderingPresetsContentProps = { + presets: ViewportPreset[]; + onClose: () => void; + viewportId: string; + commandsManager: CommandsManager; +}; + +export type VolumeRenderingOptionsProps = { + viewportId: string; + commandsManager: CommandsManager; + serviceManager: ServicesManager; + volumeRenderingQualityRange: VolumeRenderingQualityRange; +}; + +export type VolumeRenderingQualityRange = { + min: number; + max: number; + step: number; +}; + +export type VolumeRenderingQualityProps = { + viewportId: string; + commandsManager: CommandsManager; + serviceManager: ServicesManager; + volumeRenderingQualityRange: VolumeRenderingQualityRange; +}; + +export type VolumeShiftProps = { + viewportId: string; + commandsManager: CommandsManager; + serviceManager: ServicesManager; +}; + +export type VolumeShadeProps = { + viewportId: string; + commandsManager: CommandsManager; + serviceManager: ServicesManager; +}; + +export type VolumeLightingProps = { + viewportId: string; + commandsManager: CommandsManager; + serviceManager: ServicesManager; +}; diff --git a/extensions/cornerstone/src/types/WindowLevel.ts b/extensions/cornerstone/src/types/WindowLevel.ts new file mode 100644 index 000000000..556d0cad2 --- /dev/null +++ b/extensions/cornerstone/src/types/WindowLevel.ts @@ -0,0 +1,5 @@ +export type WindowLevelPreset = { + description: string; + window: string; + level: string; +}; diff --git a/extensions/cornerstone/src/utils/colormaps.js b/extensions/cornerstone/src/utils/colormaps.js new file mode 100644 index 000000000..85946725c --- /dev/null +++ b/extensions/cornerstone/src/utils/colormaps.js @@ -0,0 +1,1600 @@ +const colormaps = [ + { + ColorSpace: 'RGB', + Name: 'hsv', + name: 'hsv', + RGBPoints: [ + -1, 1, 0, 0, -0.666666, 1, 0, 1, -0.333333, 0, 0, 1, 0, 0, 1, 1, 0.33333, 0, 1, 0, 0.66666, 1, + 1, 0, 1, 1, 0, 0, + ], + description: 'HSV', + }, + { + ColorSpace: 'RGB', + Name: 'hot_iron', + name: 'hot_iron', + RGBPoints: [ + 0.0, 0.0039215686, 0.0039215686, 0.0156862745, 0.00392156862745098, 0.0039215686, + 0.0039215686, 0.0156862745, 0.00784313725490196, 0.0039215686, 0.0039215686, 0.031372549, + 0.011764705882352941, 0.0039215686, 0.0039215686, 0.0470588235, 0.01568627450980392, + 0.0039215686, 0.0039215686, 0.062745098, 0.0196078431372549, 0.0039215686, 0.0039215686, + 0.0784313725, 0.023529411764705882, 0.0039215686, 0.0039215686, 0.0941176471, + 0.027450980392156862, 0.0039215686, 0.0039215686, 0.1098039216, 0.03137254901960784, + 0.0039215686, 0.0039215686, 0.1254901961, 0.03529411764705882, 0.0039215686, 0.0039215686, + 0.1411764706, 0.0392156862745098, 0.0039215686, 0.0039215686, 0.1568627451, + 0.043137254901960784, 0.0039215686, 0.0039215686, 0.1725490196, 0.047058823529411764, + 0.0039215686, 0.0039215686, 0.1882352941, 0.050980392156862744, 0.0039215686, 0.0039215686, + 0.2039215686, 0.054901960784313725, 0.0039215686, 0.0039215686, 0.2196078431, + 0.05882352941176471, 0.0039215686, 0.0039215686, 0.2352941176, 0.06274509803921569, + 0.0039215686, 0.0039215686, 0.2509803922, 0.06666666666666667, 0.0039215686, 0.0039215686, + 0.262745098, 0.07058823529411765, 0.0039215686, 0.0039215686, 0.2784313725, + 0.07450980392156863, 0.0039215686, 0.0039215686, 0.2941176471, 0.0784313725490196, + 0.0039215686, 0.0039215686, 0.3098039216, 0.08235294117647059, 0.0039215686, 0.0039215686, + 0.3254901961, 0.08627450980392157, 0.0039215686, 0.0039215686, 0.3411764706, + 0.09019607843137255, 0.0039215686, 0.0039215686, 0.3568627451, 0.09411764705882353, + 0.0039215686, 0.0039215686, 0.3725490196, 0.09803921568627451, 0.0039215686, 0.0039215686, + 0.3882352941, 0.10196078431372549, 0.0039215686, 0.0039215686, 0.4039215686, + 0.10588235294117647, 0.0039215686, 0.0039215686, 0.4196078431, 0.10980392156862745, + 0.0039215686, 0.0039215686, 0.4352941176, 0.11372549019607843, 0.0039215686, 0.0039215686, + 0.4509803922, 0.11764705882352942, 0.0039215686, 0.0039215686, 0.4666666667, + 0.12156862745098039, 0.0039215686, 0.0039215686, 0.4823529412, 0.12549019607843137, + 0.0039215686, 0.0039215686, 0.4980392157, 0.12941176470588237, 0.0039215686, 0.0039215686, + 0.5137254902, 0.13333333333333333, 0.0039215686, 0.0039215686, 0.5294117647, + 0.13725490196078433, 0.0039215686, 0.0039215686, 0.5450980392, 0.1411764705882353, + 0.0039215686, 0.0039215686, 0.5607843137, 0.1450980392156863, 0.0039215686, 0.0039215686, + 0.5764705882, 0.14901960784313725, 0.0039215686, 0.0039215686, 0.5921568627, + 0.15294117647058825, 0.0039215686, 0.0039215686, 0.6078431373, 0.1568627450980392, + 0.0039215686, 0.0039215686, 0.6235294118, 0.1607843137254902, 0.0039215686, 0.0039215686, + 0.6392156863, 0.16470588235294117, 0.0039215686, 0.0039215686, 0.6549019608, + 0.16862745098039217, 0.0039215686, 0.0039215686, 0.6705882353, 0.17254901960784313, + 0.0039215686, 0.0039215686, 0.6862745098, 0.17647058823529413, 0.0039215686, 0.0039215686, + 0.7019607843, 0.1803921568627451, 0.0039215686, 0.0039215686, 0.7176470588, + 0.1843137254901961, 0.0039215686, 0.0039215686, 0.7333333333, 0.18823529411764706, + 0.0039215686, 0.0039215686, 0.7490196078, 0.19215686274509805, 0.0039215686, 0.0039215686, + 0.7607843137, 0.19607843137254902, 0.0039215686, 0.0039215686, 0.7764705882, 0.2, + 0.0039215686, 0.0039215686, 0.7921568627, 0.20392156862745098, 0.0039215686, 0.0039215686, + 0.8078431373, 0.20784313725490197, 0.0039215686, 0.0039215686, 0.8235294118, + 0.21176470588235294, 0.0039215686, 0.0039215686, 0.8392156863, 0.21568627450980393, + 0.0039215686, 0.0039215686, 0.8549019608, 0.2196078431372549, 0.0039215686, 0.0039215686, + 0.8705882353, 0.2235294117647059, 0.0039215686, 0.0039215686, 0.8862745098, + 0.22745098039215686, 0.0039215686, 0.0039215686, 0.9019607843, 0.23137254901960785, + 0.0039215686, 0.0039215686, 0.9176470588, 0.23529411764705885, 0.0039215686, 0.0039215686, + 0.9333333333, 0.23921568627450984, 0.0039215686, 0.0039215686, 0.9490196078, + 0.24313725490196078, 0.0039215686, 0.0039215686, 0.9647058824, 0.24705882352941178, + 0.0039215686, 0.0039215686, 0.9803921569, 0.25098039215686274, 0.0039215686, 0.0039215686, + 0.9960784314, 0.2549019607843137, 0.0039215686, 0.0039215686, 0.9960784314, + 0.25882352941176473, 0.0156862745, 0.0039215686, 0.9803921569, 0.2627450980392157, + 0.031372549, 0.0039215686, 0.9647058824, 0.26666666666666666, 0.0470588235, 0.0039215686, + 0.9490196078, 0.27058823529411763, 0.062745098, 0.0039215686, 0.9333333333, + 0.27450980392156865, 0.0784313725, 0.0039215686, 0.9176470588, 0.2784313725490196, + 0.0941176471, 0.0039215686, 0.9019607843, 0.2823529411764706, 0.1098039216, 0.0039215686, + 0.8862745098, 0.28627450980392155, 0.1254901961, 0.0039215686, 0.8705882353, + 0.2901960784313726, 0.1411764706, 0.0039215686, 0.8549019608, 0.29411764705882354, + 0.1568627451, 0.0039215686, 0.8392156863, 0.2980392156862745, 0.1725490196, 0.0039215686, + 0.8235294118, 0.30196078431372547, 0.1882352941, 0.0039215686, 0.8078431373, + 0.3058823529411765, 0.2039215686, 0.0039215686, 0.7921568627, 0.30980392156862746, + 0.2196078431, 0.0039215686, 0.7764705882, 0.3137254901960784, 0.2352941176, 0.0039215686, + 0.7607843137, 0.3176470588235294, 0.2509803922, 0.0039215686, 0.7490196078, + 0.3215686274509804, 0.262745098, 0.0039215686, 0.7333333333, 0.3254901960784314, 0.2784313725, + 0.0039215686, 0.7176470588, 0.32941176470588235, 0.2941176471, 0.0039215686, 0.7019607843, + 0.3333333333333333, 0.3098039216, 0.0039215686, 0.6862745098, 0.33725490196078434, + 0.3254901961, 0.0039215686, 0.6705882353, 0.3411764705882353, 0.3411764706, 0.0039215686, + 0.6549019608, 0.34509803921568627, 0.3568627451, 0.0039215686, 0.6392156863, + 0.34901960784313724, 0.3725490196, 0.0039215686, 0.6235294118, 0.35294117647058826, + 0.3882352941, 0.0039215686, 0.6078431373, 0.3568627450980392, 0.4039215686, 0.0039215686, + 0.5921568627, 0.3607843137254902, 0.4196078431, 0.0039215686, 0.5764705882, + 0.36470588235294116, 0.4352941176, 0.0039215686, 0.5607843137, 0.3686274509803922, + 0.4509803922, 0.0039215686, 0.5450980392, 0.37254901960784315, 0.4666666667, 0.0039215686, + 0.5294117647, 0.3764705882352941, 0.4823529412, 0.0039215686, 0.5137254902, + 0.3803921568627451, 0.4980392157, 0.0039215686, 0.4980392157, 0.3843137254901961, + 0.5137254902, 0.0039215686, 0.4823529412, 0.38823529411764707, 0.5294117647, 0.0039215686, + 0.4666666667, 0.39215686274509803, 0.5450980392, 0.0039215686, 0.4509803922, + 0.396078431372549, 0.5607843137, 0.0039215686, 0.4352941176, 0.4, 0.5764705882, 0.0039215686, + 0.4196078431, 0.403921568627451, 0.5921568627, 0.0039215686, 0.4039215686, + 0.40784313725490196, 0.6078431373, 0.0039215686, 0.3882352941, 0.4117647058823529, + 0.6235294118, 0.0039215686, 0.3725490196, 0.41568627450980394, 0.6392156863, 0.0039215686, + 0.3568627451, 0.4196078431372549, 0.6549019608, 0.0039215686, 0.3411764706, + 0.4235294117647059, 0.6705882353, 0.0039215686, 0.3254901961, 0.42745098039215684, + 0.6862745098, 0.0039215686, 0.3098039216, 0.43137254901960786, 0.7019607843, 0.0039215686, + 0.2941176471, 0.43529411764705883, 0.7176470588, 0.0039215686, 0.2784313725, + 0.4392156862745098, 0.7333333333, 0.0039215686, 0.262745098, 0.44313725490196076, + 0.7490196078, 0.0039215686, 0.2509803922, 0.4470588235294118, 0.7607843137, 0.0039215686, + 0.2352941176, 0.45098039215686275, 0.7764705882, 0.0039215686, 0.2196078431, + 0.4549019607843137, 0.7921568627, 0.0039215686, 0.2039215686, 0.4588235294117647, + 0.8078431373, 0.0039215686, 0.1882352941, 0.4627450980392157, 0.8235294118, 0.0039215686, + 0.1725490196, 0.4666666666666667, 0.8392156863, 0.0039215686, 0.1568627451, + 0.4705882352941177, 0.8549019608, 0.0039215686, 0.1411764706, 0.4745098039215686, + 0.8705882353, 0.0039215686, 0.1254901961, 0.4784313725490197, 0.8862745098, 0.0039215686, + 0.1098039216, 0.48235294117647065, 0.9019607843, 0.0039215686, 0.0941176471, + 0.48627450980392156, 0.9176470588, 0.0039215686, 0.0784313725, 0.49019607843137253, + 0.9333333333, 0.0039215686, 0.062745098, 0.49411764705882355, 0.9490196078, 0.0039215686, + 0.0470588235, 0.4980392156862745, 0.9647058824, 0.0039215686, 0.031372549, 0.5019607843137255, + 0.9803921569, 0.0039215686, 0.0156862745, 0.5058823529411764, 0.9960784314, 0.0039215686, + 0.0039215686, 0.5098039215686274, 0.9960784314, 0.0156862745, 0.0039215686, + 0.5137254901960784, 0.9960784314, 0.031372549, 0.0039215686, 0.5176470588235295, 0.9960784314, + 0.0470588235, 0.0039215686, 0.5215686274509804, 0.9960784314, 0.062745098, 0.0039215686, + 0.5254901960784314, 0.9960784314, 0.0784313725, 0.0039215686, 0.5294117647058824, + 0.9960784314, 0.0941176471, 0.0039215686, 0.5333333333333333, 0.9960784314, 0.1098039216, + 0.0039215686, 0.5372549019607843, 0.9960784314, 0.1254901961, 0.0039215686, + 0.5411764705882353, 0.9960784314, 0.1411764706, 0.0039215686, 0.5450980392156862, + 0.9960784314, 0.1568627451, 0.0039215686, 0.5490196078431373, 0.9960784314, 0.1725490196, + 0.0039215686, 0.5529411764705883, 0.9960784314, 0.1882352941, 0.0039215686, + 0.5568627450980392, 0.9960784314, 0.2039215686, 0.0039215686, 0.5607843137254902, + 0.9960784314, 0.2196078431, 0.0039215686, 0.5647058823529412, 0.9960784314, 0.2352941176, + 0.0039215686, 0.5686274509803921, 0.9960784314, 0.2509803922, 0.0039215686, + 0.5725490196078431, 0.9960784314, 0.262745098, 0.0039215686, 0.5764705882352941, 0.9960784314, + 0.2784313725, 0.0039215686, 0.5803921568627451, 0.9960784314, 0.2941176471, 0.0039215686, + 0.5843137254901961, 0.9960784314, 0.3098039216, 0.0039215686, 0.5882352941176471, + 0.9960784314, 0.3254901961, 0.0039215686, 0.592156862745098, 0.9960784314, 0.3411764706, + 0.0039215686, 0.596078431372549, 0.9960784314, 0.3568627451, 0.0039215686, 0.6, 0.9960784314, + 0.3725490196, 0.0039215686, 0.6039215686274509, 0.9960784314, 0.3882352941, 0.0039215686, + 0.6078431372549019, 0.9960784314, 0.4039215686, 0.0039215686, 0.611764705882353, 0.9960784314, + 0.4196078431, 0.0039215686, 0.615686274509804, 0.9960784314, 0.4352941176, 0.0039215686, + 0.6196078431372549, 0.9960784314, 0.4509803922, 0.0039215686, 0.6235294117647059, + 0.9960784314, 0.4666666667, 0.0039215686, 0.6274509803921569, 0.9960784314, 0.4823529412, + 0.0039215686, 0.6313725490196078, 0.9960784314, 0.4980392157, 0.0039215686, + 0.6352941176470588, 0.9960784314, 0.5137254902, 0.0039215686, 0.6392156862745098, + 0.9960784314, 0.5294117647, 0.0039215686, 0.6431372549019608, 0.9960784314, 0.5450980392, + 0.0039215686, 0.6470588235294118, 0.9960784314, 0.5607843137, 0.0039215686, + 0.6509803921568628, 0.9960784314, 0.5764705882, 0.0039215686, 0.6549019607843137, + 0.9960784314, 0.5921568627, 0.0039215686, 0.6588235294117647, 0.9960784314, 0.6078431373, + 0.0039215686, 0.6627450980392157, 0.9960784314, 0.6235294118, 0.0039215686, + 0.6666666666666666, 0.9960784314, 0.6392156863, 0.0039215686, 0.6705882352941176, + 0.9960784314, 0.6549019608, 0.0039215686, 0.6745098039215687, 0.9960784314, 0.6705882353, + 0.0039215686, 0.6784313725490196, 0.9960784314, 0.6862745098, 0.0039215686, + 0.6823529411764706, 0.9960784314, 0.7019607843, 0.0039215686, 0.6862745098039216, + 0.9960784314, 0.7176470588, 0.0039215686, 0.6901960784313725, 0.9960784314, 0.7333333333, + 0.0039215686, 0.6941176470588235, 0.9960784314, 0.7490196078, 0.0039215686, + 0.6980392156862745, 0.9960784314, 0.7607843137, 0.0039215686, 0.7019607843137254, + 0.9960784314, 0.7764705882, 0.0039215686, 0.7058823529411765, 0.9960784314, 0.7921568627, + 0.0039215686, 0.7098039215686275, 0.9960784314, 0.8078431373, 0.0039215686, + 0.7137254901960784, 0.9960784314, 0.8235294118, 0.0039215686, 0.7176470588235294, + 0.9960784314, 0.8392156863, 0.0039215686, 0.7215686274509804, 0.9960784314, 0.8549019608, + 0.0039215686, 0.7254901960784313, 0.9960784314, 0.8705882353, 0.0039215686, + 0.7294117647058823, 0.9960784314, 0.8862745098, 0.0039215686, 0.7333333333333333, + 0.9960784314, 0.9019607843, 0.0039215686, 0.7372549019607844, 0.9960784314, 0.9176470588, + 0.0039215686, 0.7411764705882353, 0.9960784314, 0.9333333333, 0.0039215686, + 0.7450980392156863, 0.9960784314, 0.9490196078, 0.0039215686, 0.7490196078431373, + 0.9960784314, 0.9647058824, 0.0039215686, 0.7529411764705882, 0.9960784314, 0.9803921569, + 0.0039215686, 0.7568627450980392, 0.9960784314, 0.9960784314, 0.0039215686, + 0.7607843137254902, 0.9960784314, 0.9960784314, 0.0196078431, 0.7647058823529411, + 0.9960784314, 0.9960784314, 0.0352941176, 0.7686274509803922, 0.9960784314, 0.9960784314, + 0.0509803922, 0.7725490196078432, 0.9960784314, 0.9960784314, 0.0666666667, + 0.7764705882352941, 0.9960784314, 0.9960784314, 0.0823529412, 0.7803921568627451, + 0.9960784314, 0.9960784314, 0.0980392157, 0.7843137254901961, 0.9960784314, 0.9960784314, + 0.1137254902, 0.788235294117647, 0.9960784314, 0.9960784314, 0.1294117647, 0.792156862745098, + 0.9960784314, 0.9960784314, 0.1450980392, 0.796078431372549, 0.9960784314, 0.9960784314, + 0.1607843137, 0.8, 0.9960784314, 0.9960784314, 0.1764705882, 0.803921568627451, 0.9960784314, + 0.9960784314, 0.1921568627, 0.807843137254902, 0.9960784314, 0.9960784314, 0.2078431373, + 0.8117647058823529, 0.9960784314, 0.9960784314, 0.2235294118, 0.8156862745098039, + 0.9960784314, 0.9960784314, 0.2392156863, 0.8196078431372549, 0.9960784314, 0.9960784314, + 0.2509803922, 0.8235294117647058, 0.9960784314, 0.9960784314, 0.2666666667, + 0.8274509803921568, 0.9960784314, 0.9960784314, 0.2823529412, 0.8313725490196079, + 0.9960784314, 0.9960784314, 0.2980392157, 0.8352941176470589, 0.9960784314, 0.9960784314, + 0.3137254902, 0.8392156862745098, 0.9960784314, 0.9960784314, 0.3333333333, + 0.8431372549019608, 0.9960784314, 0.9960784314, 0.3490196078, 0.8470588235294118, + 0.9960784314, 0.9960784314, 0.3647058824, 0.8509803921568627, 0.9960784314, 0.9960784314, + 0.3803921569, 0.8549019607843137, 0.9960784314, 0.9960784314, 0.3960784314, + 0.8588235294117647, 0.9960784314, 0.9960784314, 0.4117647059, 0.8627450980392157, + 0.9960784314, 0.9960784314, 0.4274509804, 0.8666666666666667, 0.9960784314, 0.9960784314, + 0.4431372549, 0.8705882352941177, 0.9960784314, 0.9960784314, 0.4588235294, + 0.8745098039215686, 0.9960784314, 0.9960784314, 0.4745098039, 0.8784313725490196, + 0.9960784314, 0.9960784314, 0.4901960784, 0.8823529411764706, 0.9960784314, 0.9960784314, + 0.5058823529, 0.8862745098039215, 0.9960784314, 0.9960784314, 0.5215686275, + 0.8901960784313725, 0.9960784314, 0.9960784314, 0.537254902, 0.8941176470588236, 0.9960784314, + 0.9960784314, 0.5529411765, 0.8980392156862745, 0.9960784314, 0.9960784314, 0.568627451, + 0.9019607843137255, 0.9960784314, 0.9960784314, 0.5843137255, 0.9058823529411765, + 0.9960784314, 0.9960784314, 0.6, 0.9098039215686274, 0.9960784314, 0.9960784314, 0.6156862745, + 0.9137254901960784, 0.9960784314, 0.9960784314, 0.631372549, 0.9176470588235294, 0.9960784314, + 0.9960784314, 0.6470588235, 0.9215686274509803, 0.9960784314, 0.9960784314, 0.6666666667, + 0.9254901960784314, 0.9960784314, 0.9960784314, 0.6823529412, 0.9294117647058824, + 0.9960784314, 0.9960784314, 0.6980392157, 0.9333333333333333, 0.9960784314, 0.9960784314, + 0.7137254902, 0.9372549019607843, 0.9960784314, 0.9960784314, 0.7294117647, + 0.9411764705882354, 0.9960784314, 0.9960784314, 0.7450980392, 0.9450980392156864, + 0.9960784314, 0.9960784314, 0.7568627451, 0.9490196078431372, 0.9960784314, 0.9960784314, + 0.7725490196, 0.9529411764705882, 0.9960784314, 0.9960784314, 0.7882352941, + 0.9568627450980394, 0.9960784314, 0.9960784314, 0.8039215686, 0.9607843137254903, + 0.9960784314, 0.9960784314, 0.8196078431, 0.9647058823529413, 0.9960784314, 0.9960784314, + 0.8352941176, 0.9686274509803922, 0.9960784314, 0.9960784314, 0.8509803922, + 0.9725490196078431, 0.9960784314, 0.9960784314, 0.8666666667, 0.9764705882352941, + 0.9960784314, 0.9960784314, 0.8823529412, 0.9803921568627451, 0.9960784314, 0.9960784314, + 0.8980392157, 0.984313725490196, 0.9960784314, 0.9960784314, 0.9137254902, 0.9882352941176471, + 0.9960784314, 0.9960784314, 0.9294117647, 0.9921568627450981, 0.9960784314, 0.9960784314, + 0.9450980392, 0.996078431372549, 0.9960784314, 0.9960784314, 0.9607843137, 1.0, 0.9960784314, + 0.9960784314, 0.9607843137, + ], + description: 'Hot Iron', + }, + { + ColorSpace: 'RGB', + Name: 'red_hot', + name: 'red_hot', + RGBPoints: [ + 0.0, 0.0, 0.0, 0.0, 0.00392156862745098, 0.0, 0.0, 0.0, 0.00784313725490196, 0.0, 0.0, 0.0, + 0.011764705882352941, 0.0, 0.0, 0.0, 0.01568627450980392, 0.0039215686, 0.0039215686, + 0.0039215686, 0.0196078431372549, 0.0039215686, 0.0039215686, 0.0039215686, + 0.023529411764705882, 0.0039215686, 0.0039215686, 0.0039215686, 0.027450980392156862, + 0.0039215686, 0.0039215686, 0.0039215686, 0.03137254901960784, 0.0039215686, 0.0039215686, + 0.0039215686, 0.03529411764705882, 0.0156862745, 0.0, 0.0, 0.0392156862745098, 0.0274509804, + 0.0, 0.0, 0.043137254901960784, 0.0392156863, 0.0, 0.0, 0.047058823529411764, 0.0509803922, + 0.0, 0.0, 0.050980392156862744, 0.062745098, 0.0, 0.0, 0.054901960784313725, 0.0784313725, + 0.0, 0.0, 0.05882352941176471, 0.0901960784, 0.0, 0.0, 0.06274509803921569, 0.1058823529, 0.0, + 0.0, 0.06666666666666667, 0.1176470588, 0.0, 0.0, 0.07058823529411765, 0.1294117647, 0.0, 0.0, + 0.07450980392156863, 0.1411764706, 0.0, 0.0, 0.0784313725490196, 0.1529411765, 0.0, 0.0, + 0.08235294117647059, 0.1647058824, 0.0, 0.0, 0.08627450980392157, 0.1764705882, 0.0, 0.0, + 0.09019607843137255, 0.1882352941, 0.0, 0.0, 0.09411764705882353, 0.2039215686, 0.0, 0.0, + 0.09803921568627451, 0.2156862745, 0.0, 0.0, 0.10196078431372549, 0.2274509804, 0.0, 0.0, + 0.10588235294117647, 0.2392156863, 0.0, 0.0, 0.10980392156862745, 0.2549019608, 0.0, 0.0, + 0.11372549019607843, 0.2666666667, 0.0, 0.0, 0.11764705882352942, 0.2784313725, 0.0, 0.0, + 0.12156862745098039, 0.2901960784, 0.0, 0.0, 0.12549019607843137, 0.3058823529, 0.0, 0.0, + 0.12941176470588237, 0.3176470588, 0.0, 0.0, 0.13333333333333333, 0.3294117647, 0.0, 0.0, + 0.13725490196078433, 0.3411764706, 0.0, 0.0, 0.1411764705882353, 0.3529411765, 0.0, 0.0, + 0.1450980392156863, 0.3647058824, 0.0, 0.0, 0.14901960784313725, 0.3764705882, 0.0, 0.0, + 0.15294117647058825, 0.3882352941, 0.0, 0.0, 0.1568627450980392, 0.4039215686, 0.0, 0.0, + 0.1607843137254902, 0.4156862745, 0.0, 0.0, 0.16470588235294117, 0.431372549, 0.0, 0.0, + 0.16862745098039217, 0.4431372549, 0.0, 0.0, 0.17254901960784313, 0.4588235294, 0.0, 0.0, + 0.17647058823529413, 0.4705882353, 0.0, 0.0, 0.1803921568627451, 0.4823529412, 0.0, 0.0, + 0.1843137254901961, 0.4941176471, 0.0, 0.0, 0.18823529411764706, 0.5098039216, 0.0, 0.0, + 0.19215686274509805, 0.5215686275, 0.0, 0.0, 0.19607843137254902, 0.5333333333, 0.0, 0.0, 0.2, + 0.5450980392, 0.0, 0.0, 0.20392156862745098, 0.5568627451, 0.0, 0.0, 0.20784313725490197, + 0.568627451, 0.0, 0.0, 0.21176470588235294, 0.5803921569, 0.0, 0.0, 0.21568627450980393, + 0.5921568627, 0.0, 0.0, 0.2196078431372549, 0.6078431373, 0.0, 0.0, 0.2235294117647059, + 0.6196078431, 0.0, 0.0, 0.22745098039215686, 0.631372549, 0.0, 0.0, 0.23137254901960785, + 0.6431372549, 0.0, 0.0, 0.23529411764705885, 0.6588235294, 0.0, 0.0, 0.23921568627450984, + 0.6705882353, 0.0, 0.0, 0.24313725490196078, 0.6823529412, 0.0, 0.0, 0.24705882352941178, + 0.6941176471, 0.0, 0.0, 0.25098039215686274, 0.7098039216, 0.0, 0.0, 0.2549019607843137, + 0.7215686275, 0.0, 0.0, 0.25882352941176473, 0.7333333333, 0.0, 0.0, 0.2627450980392157, + 0.7450980392, 0.0, 0.0, 0.26666666666666666, 0.7568627451, 0.0, 0.0, 0.27058823529411763, + 0.768627451, 0.0, 0.0, 0.27450980392156865, 0.7843137255, 0.0, 0.0, 0.2784313725490196, + 0.7960784314, 0.0, 0.0, 0.2823529411764706, 0.8117647059, 0.0, 0.0, 0.28627450980392155, + 0.8235294118, 0.0, 0.0, 0.2901960784313726, 0.8352941176, 0.0, 0.0, 0.29411764705882354, + 0.8470588235, 0.0, 0.0, 0.2980392156862745, 0.862745098, 0.0, 0.0, 0.30196078431372547, + 0.8745098039, 0.0, 0.0, 0.3058823529411765, 0.8862745098, 0.0, 0.0, 0.30980392156862746, + 0.8980392157, 0.0, 0.0, 0.3137254901960784, 0.9137254902, 0.0, 0.0, 0.3176470588235294, + 0.9254901961, 0.0, 0.0, 0.3215686274509804, 0.937254902, 0.0, 0.0, 0.3254901960784314, + 0.9490196078, 0.0, 0.0, 0.32941176470588235, 0.9607843137, 0.0, 0.0, 0.3333333333333333, + 0.968627451, 0.0, 0.0, 0.33725490196078434, 0.9803921569, 0.0039215686, 0.0, + 0.3411764705882353, 0.9882352941, 0.0078431373, 0.0, 0.34509803921568627, 1.0, 0.0117647059, + 0.0, 0.34901960784313724, 1.0, 0.0235294118, 0.0, 0.35294117647058826, 1.0, 0.0352941176, 0.0, + 0.3568627450980392, 1.0, 0.0470588235, 0.0, 0.3607843137254902, 1.0, 0.062745098, 0.0, + 0.36470588235294116, 1.0, 0.0745098039, 0.0, 0.3686274509803922, 1.0, 0.0862745098, 0.0, + 0.37254901960784315, 1.0, 0.0980392157, 0.0, 0.3764705882352941, 1.0, 0.1137254902, 0.0, + 0.3803921568627451, 1.0, 0.1254901961, 0.0, 0.3843137254901961, 1.0, 0.137254902, 0.0, + 0.38823529411764707, 1.0, 0.1490196078, 0.0, 0.39215686274509803, 1.0, 0.1647058824, 0.0, + 0.396078431372549, 1.0, 0.1764705882, 0.0, 0.4, 1.0, 0.1882352941, 0.0, 0.403921568627451, + 1.0, 0.2, 0.0, 0.40784313725490196, 1.0, 0.2156862745, 0.0, 0.4117647058823529, 1.0, + 0.2274509804, 0.0, 0.41568627450980394, 1.0, 0.2392156863, 0.0, 0.4196078431372549, 1.0, + 0.2509803922, 0.0, 0.4235294117647059, 1.0, 0.2666666667, 0.0, 0.42745098039215684, 1.0, + 0.2784313725, 0.0, 0.43137254901960786, 1.0, 0.2901960784, 0.0, 0.43529411764705883, 1.0, + 0.3019607843, 0.0, 0.4392156862745098, 1.0, 0.3176470588, 0.0, 0.44313725490196076, 1.0, + 0.3294117647, 0.0, 0.4470588235294118, 1.0, 0.3411764706, 0.0, 0.45098039215686275, 1.0, + 0.3529411765, 0.0, 0.4549019607843137, 1.0, 0.368627451, 0.0, 0.4588235294117647, 1.0, + 0.3803921569, 0.0, 0.4627450980392157, 1.0, 0.3921568627, 0.0, 0.4666666666666667, 1.0, + 0.4039215686, 0.0, 0.4705882352941177, 1.0, 0.4156862745, 0.0, 0.4745098039215686, 1.0, + 0.4274509804, 0.0, 0.4784313725490197, 1.0, 0.4392156863, 0.0, 0.48235294117647065, 1.0, + 0.4509803922, 0.0, 0.48627450980392156, 1.0, 0.4666666667, 0.0, 0.49019607843137253, 1.0, + 0.4784313725, 0.0, 0.49411764705882355, 1.0, 0.4941176471, 0.0, 0.4980392156862745, 1.0, + 0.5058823529, 0.0, 0.5019607843137255, 1.0, 0.5215686275, 0.0, 0.5058823529411764, 1.0, + 0.5333333333, 0.0, 0.5098039215686274, 1.0, 0.5450980392, 0.0, 0.5137254901960784, 1.0, + 0.5568627451, 0.0, 0.5176470588235295, 1.0, 0.568627451, 0.0, 0.5215686274509804, 1.0, + 0.5803921569, 0.0, 0.5254901960784314, 1.0, 0.5921568627, 0.0, 0.5294117647058824, 1.0, + 0.6039215686, 0.0, 0.5333333333333333, 1.0, 0.6196078431, 0.0, 0.5372549019607843, 1.0, + 0.631372549, 0.0, 0.5411764705882353, 1.0, 0.6431372549, 0.0, 0.5450980392156862, 1.0, + 0.6549019608, 0.0, 0.5490196078431373, 1.0, 0.6705882353, 0.0, 0.5529411764705883, 1.0, + 0.6823529412, 0.0, 0.5568627450980392, 1.0, 0.6941176471, 0.0, 0.5607843137254902, 1.0, + 0.7058823529, 0.0, 0.5647058823529412, 1.0, 0.7215686275, 0.0, 0.5686274509803921, 1.0, + 0.7333333333, 0.0, 0.5725490196078431, 1.0, 0.7450980392, 0.0, 0.5764705882352941, 1.0, + 0.7568627451, 0.0, 0.5803921568627451, 1.0, 0.7725490196, 0.0, 0.5843137254901961, 1.0, + 0.7843137255, 0.0, 0.5882352941176471, 1.0, 0.7960784314, 0.0, 0.592156862745098, 1.0, + 0.8078431373, 0.0, 0.596078431372549, 1.0, 0.8196078431, 0.0, 0.6, 1.0, 0.831372549, 0.0, + 0.6039215686274509, 1.0, 0.8470588235, 0.0, 0.6078431372549019, 1.0, 0.8588235294, 0.0, + 0.611764705882353, 1.0, 0.8745098039, 0.0, 0.615686274509804, 1.0, 0.8862745098, 0.0, + 0.6196078431372549, 1.0, 0.8980392157, 0.0, 0.6235294117647059, 1.0, 0.9098039216, 0.0, + 0.6274509803921569, 1.0, 0.9254901961, 0.0, 0.6313725490196078, 1.0, 0.937254902, 0.0, + 0.6352941176470588, 1.0, 0.9490196078, 0.0, 0.6392156862745098, 1.0, 0.9607843137, 0.0, + 0.6431372549019608, 1.0, 0.9764705882, 0.0, 0.6470588235294118, 1.0, 0.9803921569, + 0.0039215686, 0.6509803921568628, 1.0, 0.9882352941, 0.0117647059, 0.6549019607843137, 1.0, + 0.9921568627, 0.0156862745, 0.6588235294117647, 1.0, 1.0, 0.0235294118, 0.6627450980392157, + 1.0, 1.0, 0.0352941176, 0.6666666666666666, 1.0, 1.0, 0.0470588235, 0.6705882352941176, 1.0, + 1.0, 0.0588235294, 0.6745098039215687, 1.0, 1.0, 0.0745098039, 0.6784313725490196, 1.0, 1.0, + 0.0862745098, 0.6823529411764706, 1.0, 1.0, 0.0980392157, 0.6862745098039216, 1.0, 1.0, + 0.1098039216, 0.6901960784313725, 1.0, 1.0, 0.1254901961, 0.6941176470588235, 1.0, 1.0, + 0.137254902, 0.6980392156862745, 1.0, 1.0, 0.1490196078, 0.7019607843137254, 1.0, 1.0, + 0.1607843137, 0.7058823529411765, 1.0, 1.0, 0.1764705882, 0.7098039215686275, 1.0, 1.0, + 0.1882352941, 0.7137254901960784, 1.0, 1.0, 0.2, 0.7176470588235294, 1.0, 1.0, 0.2117647059, + 0.7215686274509804, 1.0, 1.0, 0.2274509804, 0.7254901960784313, 1.0, 1.0, 0.2392156863, + 0.7294117647058823, 1.0, 1.0, 0.2509803922, 0.7333333333333333, 1.0, 1.0, 0.262745098, + 0.7372549019607844, 1.0, 1.0, 0.2784313725, 0.7411764705882353, 1.0, 1.0, 0.2901960784, + 0.7450980392156863, 1.0, 1.0, 0.3019607843, 0.7490196078431373, 1.0, 1.0, 0.3137254902, + 0.7529411764705882, 1.0, 1.0, 0.3294117647, 0.7568627450980392, 1.0, 1.0, 0.3411764706, + 0.7607843137254902, 1.0, 1.0, 0.3529411765, 0.7647058823529411, 1.0, 1.0, 0.3647058824, + 0.7686274509803922, 1.0, 1.0, 0.3803921569, 0.7725490196078432, 1.0, 1.0, 0.3921568627, + 0.7764705882352941, 1.0, 1.0, 0.4039215686, 0.7803921568627451, 1.0, 1.0, 0.4156862745, + 0.7843137254901961, 1.0, 1.0, 0.431372549, 0.788235294117647, 1.0, 1.0, 0.4431372549, + 0.792156862745098, 1.0, 1.0, 0.4549019608, 0.796078431372549, 1.0, 1.0, 0.4666666667, 0.8, + 1.0, 1.0, 0.4784313725, 0.803921568627451, 1.0, 1.0, 0.4901960784, 0.807843137254902, 1.0, + 1.0, 0.5019607843, 0.8117647058823529, 1.0, 1.0, 0.5137254902, 0.8156862745098039, 1.0, 1.0, + 0.5294117647, 0.8196078431372549, 1.0, 1.0, 0.5411764706, 0.8235294117647058, 1.0, 1.0, + 0.5568627451, 0.8274509803921568, 1.0, 1.0, 0.568627451, 0.8313725490196079, 1.0, 1.0, + 0.5843137255, 0.8352941176470589, 1.0, 1.0, 0.5960784314, 0.8392156862745098, 1.0, 1.0, + 0.6078431373, 0.8431372549019608, 1.0, 1.0, 0.6196078431, 0.8470588235294118, 1.0, 1.0, + 0.631372549, 0.8509803921568627, 1.0, 1.0, 0.6431372549, 0.8549019607843137, 1.0, 1.0, + 0.6549019608, 0.8588235294117647, 1.0, 1.0, 0.6666666667, 0.8627450980392157, 1.0, 1.0, + 0.6823529412, 0.8666666666666667, 1.0, 1.0, 0.6941176471, 0.8705882352941177, 1.0, 1.0, + 0.7058823529, 0.8745098039215686, 1.0, 1.0, 0.7176470588, 0.8784313725490196, 1.0, 1.0, + 0.7333333333, 0.8823529411764706, 1.0, 1.0, 0.7450980392, 0.8862745098039215, 1.0, 1.0, + 0.7568627451, 0.8901960784313725, 1.0, 1.0, 0.768627451, 0.8941176470588236, 1.0, 1.0, + 0.7843137255, 0.8980392156862745, 1.0, 1.0, 0.7960784314, 0.9019607843137255, 1.0, 1.0, + 0.8078431373, 0.9058823529411765, 1.0, 1.0, 0.8196078431, 0.9098039215686274, 1.0, 1.0, + 0.8352941176, 0.9137254901960784, 1.0, 1.0, 0.8470588235, 0.9176470588235294, 1.0, 1.0, + 0.8588235294, 0.9215686274509803, 1.0, 1.0, 0.8705882353, 0.9254901960784314, 1.0, 1.0, + 0.8823529412, 0.9294117647058824, 1.0, 1.0, 0.8941176471, 0.9333333333333333, 1.0, 1.0, + 0.9098039216, 0.9372549019607843, 1.0, 1.0, 0.9215686275, 0.9411764705882354, 1.0, 1.0, + 0.937254902, 0.9450980392156864, 1.0, 1.0, 0.9490196078, 0.9490196078431372, 1.0, 1.0, + 0.9607843137, 0.9529411764705882, 1.0, 1.0, 0.9725490196, 0.9568627450980394, 1.0, 1.0, + 0.9882352941, 0.9607843137254903, 1.0, 1.0, 0.9882352941, 0.9647058823529413, 1.0, 1.0, + 0.9921568627, 0.9686274509803922, 1.0, 1.0, 0.9960784314, 0.9725490196078431, 1.0, 1.0, 1.0, + 0.9764705882352941, 1.0, 1.0, 1.0, 0.9803921568627451, 1.0, 1.0, 1.0, 0.984313725490196, 1.0, + 1.0, 1.0, 0.9882352941176471, 1.0, 1.0, 1.0, 0.9921568627450981, 1.0, 1.0, 1.0, + 0.996078431372549, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + ], + description: 'Red Hot', + }, + { + ColorSpace: 'RGB', + Name: 's_pet', + name: 's_pet', + RGBPoints: [ + 0.0, 0.0156862745, 0.0039215686, 0.0156862745, 0.00392156862745098, 0.0156862745, + 0.0039215686, 0.0156862745, 0.00784313725490196, 0.0274509804, 0.0039215686, 0.031372549, + 0.011764705882352941, 0.0352941176, 0.0039215686, 0.0509803922, 0.01568627450980392, + 0.0392156863, 0.0039215686, 0.0666666667, 0.0196078431372549, 0.0509803922, 0.0039215686, + 0.0823529412, 0.023529411764705882, 0.062745098, 0.0039215686, 0.0980392157, + 0.027450980392156862, 0.0705882353, 0.0039215686, 0.1176470588, 0.03137254901960784, + 0.0745098039, 0.0039215686, 0.1333333333, 0.03529411764705882, 0.0862745098, 0.0039215686, + 0.1490196078, 0.0392156862745098, 0.0980392157, 0.0039215686, 0.1647058824, + 0.043137254901960784, 0.1058823529, 0.0039215686, 0.1843137255, 0.047058823529411764, + 0.1098039216, 0.0039215686, 0.2, 0.050980392156862744, 0.1215686275, 0.0039215686, + 0.2156862745, 0.054901960784313725, 0.1333333333, 0.0039215686, 0.231372549, + 0.05882352941176471, 0.137254902, 0.0039215686, 0.2509803922, 0.06274509803921569, + 0.1490196078, 0.0039215686, 0.262745098, 0.06666666666666667, 0.1607843137, 0.0039215686, + 0.2784313725, 0.07058823529411765, 0.168627451, 0.0039215686, 0.2941176471, + 0.07450980392156863, 0.1725490196, 0.0039215686, 0.3137254902, 0.0784313725490196, + 0.1843137255, 0.0039215686, 0.3294117647, 0.08235294117647059, 0.1960784314, 0.0039215686, + 0.3450980392, 0.08627450980392157, 0.2039215686, 0.0039215686, 0.3607843137, + 0.09019607843137255, 0.2078431373, 0.0039215686, 0.3803921569, 0.09411764705882353, + 0.2196078431, 0.0039215686, 0.3960784314, 0.09803921568627451, 0.231372549, 0.0039215686, + 0.4117647059, 0.10196078431372549, 0.2392156863, 0.0039215686, 0.4274509804, + 0.10588235294117647, 0.2431372549, 0.0039215686, 0.4470588235, 0.10980392156862745, + 0.2509803922, 0.0039215686, 0.462745098, 0.11372549019607843, 0.262745098, 0.0039215686, + 0.4784313725, 0.11764705882352942, 0.2666666667, 0.0039215686, 0.4980392157, + 0.12156862745098039, 0.2666666667, 0.0039215686, 0.4980392157, 0.12549019607843137, + 0.262745098, 0.0039215686, 0.5137254902, 0.12941176470588237, 0.2509803922, 0.0039215686, + 0.5294117647, 0.13333333333333333, 0.2431372549, 0.0039215686, 0.5450980392, + 0.13725490196078433, 0.2392156863, 0.0039215686, 0.5607843137, 0.1411764705882353, + 0.231372549, 0.0039215686, 0.5764705882, 0.1450980392156863, 0.2196078431, 0.0039215686, + 0.5921568627, 0.14901960784313725, 0.2078431373, 0.0039215686, 0.6078431373, + 0.15294117647058825, 0.2039215686, 0.0039215686, 0.6235294118, 0.1568627450980392, + 0.1960784314, 0.0039215686, 0.6392156863, 0.1607843137254902, 0.1843137255, 0.0039215686, + 0.6549019608, 0.16470588235294117, 0.1725490196, 0.0039215686, 0.6705882353, + 0.16862745098039217, 0.168627451, 0.0039215686, 0.6862745098, 0.17254901960784313, + 0.1607843137, 0.0039215686, 0.7019607843, 0.17647058823529413, 0.1490196078, 0.0039215686, + 0.7176470588, 0.1803921568627451, 0.137254902, 0.0039215686, 0.7333333333, 0.1843137254901961, + 0.1333333333, 0.0039215686, 0.7490196078, 0.18823529411764706, 0.1215686275, 0.0039215686, + 0.7607843137, 0.19215686274509805, 0.1098039216, 0.0039215686, 0.7764705882, + 0.19607843137254902, 0.1058823529, 0.0039215686, 0.7921568627, 0.2, 0.0980392157, + 0.0039215686, 0.8078431373, 0.20392156862745098, 0.0862745098, 0.0039215686, 0.8235294118, + 0.20784313725490197, 0.0745098039, 0.0039215686, 0.8392156863, 0.21176470588235294, + 0.0705882353, 0.0039215686, 0.8549019608, 0.21568627450980393, 0.062745098, 0.0039215686, + 0.8705882353, 0.2196078431372549, 0.0509803922, 0.0039215686, 0.8862745098, + 0.2235294117647059, 0.0392156863, 0.0039215686, 0.9019607843, 0.22745098039215686, + 0.0352941176, 0.0039215686, 0.9176470588, 0.23137254901960785, 0.0274509804, 0.0039215686, + 0.9333333333, 0.23529411764705885, 0.0156862745, 0.0039215686, 0.9490196078, + 0.23921568627450984, 0.0078431373, 0.0039215686, 0.9647058824, 0.24313725490196078, + 0.0039215686, 0.0039215686, 0.9960784314, 0.24705882352941178, 0.0039215686, 0.0039215686, + 0.9960784314, 0.25098039215686274, 0.0039215686, 0.0196078431, 0.9647058824, + 0.2549019607843137, 0.0039215686, 0.0392156863, 0.9490196078, 0.25882352941176473, + 0.0039215686, 0.0549019608, 0.9333333333, 0.2627450980392157, 0.0039215686, 0.0745098039, + 0.9176470588, 0.26666666666666666, 0.0039215686, 0.0901960784, 0.9019607843, + 0.27058823529411763, 0.0039215686, 0.1098039216, 0.8862745098, 0.27450980392156865, + 0.0039215686, 0.1254901961, 0.8705882353, 0.2784313725490196, 0.0039215686, 0.1450980392, + 0.8549019608, 0.2823529411764706, 0.0039215686, 0.1607843137, 0.8392156863, + 0.28627450980392155, 0.0039215686, 0.1803921569, 0.8235294118, 0.2901960784313726, + 0.0039215686, 0.1960784314, 0.8078431373, 0.29411764705882354, 0.0039215686, 0.2156862745, + 0.7921568627, 0.2980392156862745, 0.0039215686, 0.231372549, 0.7764705882, + 0.30196078431372547, 0.0039215686, 0.2509803922, 0.7607843137, 0.3058823529411765, + 0.0039215686, 0.262745098, 0.7490196078, 0.30980392156862746, 0.0039215686, 0.2823529412, + 0.7333333333, 0.3137254901960784, 0.0039215686, 0.2980392157, 0.7176470588, + 0.3176470588235294, 0.0039215686, 0.3176470588, 0.7019607843, 0.3215686274509804, + 0.0039215686, 0.3333333333, 0.6862745098, 0.3254901960784314, 0.0039215686, 0.3529411765, + 0.6705882353, 0.32941176470588235, 0.0039215686, 0.368627451, 0.6549019608, + 0.3333333333333333, 0.0039215686, 0.3882352941, 0.6392156863, 0.33725490196078434, + 0.0039215686, 0.4039215686, 0.6235294118, 0.3411764705882353, 0.0039215686, 0.4235294118, + 0.6078431373, 0.34509803921568627, 0.0039215686, 0.4392156863, 0.5921568627, + 0.34901960784313724, 0.0039215686, 0.4588235294, 0.5764705882, 0.35294117647058826, + 0.0039215686, 0.4745098039, 0.5607843137, 0.3568627450980392, 0.0039215686, 0.4941176471, + 0.5450980392, 0.3607843137254902, 0.0039215686, 0.5098039216, 0.5294117647, + 0.36470588235294116, 0.0039215686, 0.5294117647, 0.5137254902, 0.3686274509803922, + 0.0039215686, 0.5450980392, 0.4980392157, 0.37254901960784315, 0.0039215686, 0.5647058824, + 0.4784313725, 0.3764705882352941, 0.0039215686, 0.5803921569, 0.462745098, 0.3803921568627451, + 0.0039215686, 0.6, 0.4470588235, 0.3843137254901961, 0.0039215686, 0.6156862745, 0.4274509804, + 0.38823529411764707, 0.0039215686, 0.6352941176, 0.4117647059, 0.39215686274509803, + 0.0039215686, 0.6509803922, 0.3960784314, 0.396078431372549, 0.0039215686, 0.6705882353, + 0.3803921569, 0.4, 0.0039215686, 0.6862745098, 0.3607843137, 0.403921568627451, 0.0039215686, + 0.7058823529, 0.3450980392, 0.40784313725490196, 0.0039215686, 0.7215686275, 0.3294117647, + 0.4117647058823529, 0.0039215686, 0.7411764706, 0.3137254902, 0.41568627450980394, + 0.0039215686, 0.7529411765, 0.2941176471, 0.4196078431372549, 0.0039215686, 0.7960784314, + 0.2784313725, 0.4235294117647059, 0.0039215686, 0.7960784314, 0.262745098, + 0.42745098039215684, 0.0392156863, 0.8039215686, 0.2509803922, 0.43137254901960786, + 0.0745098039, 0.8117647059, 0.231372549, 0.43529411764705883, 0.1098039216, 0.8196078431, + 0.2156862745, 0.4392156862745098, 0.1450980392, 0.8274509804, 0.2, 0.44313725490196076, + 0.1803921569, 0.8352941176, 0.1843137255, 0.4470588235294118, 0.2156862745, 0.8431372549, + 0.1647058824, 0.45098039215686275, 0.2509803922, 0.8509803922, 0.1490196078, + 0.4549019607843137, 0.2823529412, 0.8588235294, 0.1333333333, 0.4588235294117647, + 0.3176470588, 0.8666666667, 0.1176470588, 0.4627450980392157, 0.3529411765, 0.8745098039, + 0.0980392157, 0.4666666666666667, 0.3882352941, 0.8823529412, 0.0823529412, + 0.4705882352941177, 0.4235294118, 0.8901960784, 0.0666666667, 0.4745098039215686, + 0.4588235294, 0.8980392157, 0.0509803922, 0.4784313725490197, 0.4941176471, 0.9058823529, + 0.0431372549, 0.48235294117647065, 0.5294117647, 0.9137254902, 0.031372549, + 0.48627450980392156, 0.5647058824, 0.9215686275, 0.0196078431, 0.49019607843137253, 0.6, + 0.9294117647, 0.0078431373, 0.49411764705882355, 0.6352941176, 0.937254902, 0.0039215686, + 0.4980392156862745, 0.6705882353, 0.9450980392, 0.0039215686, 0.5019607843137255, + 0.7058823529, 0.9490196078, 0.0039215686, 0.5058823529411764, 0.7411764706, 0.9568627451, + 0.0039215686, 0.5098039215686274, 0.7725490196, 0.9607843137, 0.0039215686, + 0.5137254901960784, 0.8078431373, 0.968627451, 0.0039215686, 0.5176470588235295, 0.8431372549, + 0.9725490196, 0.0039215686, 0.5215686274509804, 0.8784313725, 0.9803921569, 0.0039215686, + 0.5254901960784314, 0.9137254902, 0.9843137255, 0.0039215686, 0.5294117647058824, + 0.9490196078, 0.9921568627, 0.0039215686, 0.5333333333333333, 0.9960784314, 0.9960784314, + 0.0039215686, 0.5372549019607843, 0.9960784314, 0.9960784314, 0.0039215686, + 0.5411764705882353, 0.9960784314, 0.9921568627, 0.0039215686, 0.5450980392156862, + 0.9960784314, 0.9843137255, 0.0039215686, 0.5490196078431373, 0.9960784314, 0.9764705882, + 0.0039215686, 0.5529411764705883, 0.9960784314, 0.968627451, 0.0039215686, 0.5568627450980392, + 0.9960784314, 0.9607843137, 0.0039215686, 0.5607843137254902, 0.9960784314, 0.9529411765, + 0.0039215686, 0.5647058823529412, 0.9960784314, 0.9450980392, 0.0039215686, + 0.5686274509803921, 0.9960784314, 0.937254902, 0.0039215686, 0.5725490196078431, 0.9960784314, + 0.9294117647, 0.0039215686, 0.5764705882352941, 0.9960784314, 0.9215686275, 0.0039215686, + 0.5803921568627451, 0.9960784314, 0.9137254902, 0.0039215686, 0.5843137254901961, + 0.9960784314, 0.9058823529, 0.0039215686, 0.5882352941176471, 0.9960784314, 0.8980392157, + 0.0039215686, 0.592156862745098, 0.9960784314, 0.8901960784, 0.0039215686, 0.596078431372549, + 0.9960784314, 0.8823529412, 0.0039215686, 0.6, 0.9960784314, 0.8745098039, 0.0039215686, + 0.6039215686274509, 0.9960784314, 0.8666666667, 0.0039215686, 0.6078431372549019, + 0.9960784314, 0.8588235294, 0.0039215686, 0.611764705882353, 0.9960784314, 0.8509803922, + 0.0039215686, 0.615686274509804, 0.9960784314, 0.8431372549, 0.0039215686, 0.6196078431372549, + 0.9960784314, 0.8352941176, 0.0039215686, 0.6235294117647059, 0.9960784314, 0.8274509804, + 0.0039215686, 0.6274509803921569, 0.9960784314, 0.8196078431, 0.0039215686, + 0.6313725490196078, 0.9960784314, 0.8117647059, 0.0039215686, 0.6352941176470588, + 0.9960784314, 0.8039215686, 0.0039215686, 0.6392156862745098, 0.9960784314, 0.7960784314, + 0.0039215686, 0.6431372549019608, 0.9960784314, 0.7882352941, 0.0039215686, + 0.6470588235294118, 0.9960784314, 0.7803921569, 0.0039215686, 0.6509803921568628, + 0.9960784314, 0.7725490196, 0.0039215686, 0.6549019607843137, 0.9960784314, 0.7647058824, + 0.0039215686, 0.6588235294117647, 0.9960784314, 0.7568627451, 0.0039215686, + 0.6627450980392157, 0.9960784314, 0.7490196078, 0.0039215686, 0.6666666666666666, + 0.9960784314, 0.7450980392, 0.0039215686, 0.6705882352941176, 0.9960784314, 0.737254902, + 0.0039215686, 0.6745098039215687, 0.9960784314, 0.7294117647, 0.0039215686, + 0.6784313725490196, 0.9960784314, 0.7215686275, 0.0039215686, 0.6823529411764706, + 0.9960784314, 0.7137254902, 0.0039215686, 0.6862745098039216, 0.9960784314, 0.7058823529, + 0.0039215686, 0.6901960784313725, 0.9960784314, 0.6980392157, 0.0039215686, + 0.6941176470588235, 0.9960784314, 0.6901960784, 0.0039215686, 0.6980392156862745, + 0.9960784314, 0.6823529412, 0.0039215686, 0.7019607843137254, 0.9960784314, 0.6745098039, + 0.0039215686, 0.7058823529411765, 0.9960784314, 0.6666666667, 0.0039215686, + 0.7098039215686275, 0.9960784314, 0.6588235294, 0.0039215686, 0.7137254901960784, + 0.9960784314, 0.6509803922, 0.0039215686, 0.7176470588235294, 0.9960784314, 0.6431372549, + 0.0039215686, 0.7215686274509804, 0.9960784314, 0.6352941176, 0.0039215686, + 0.7254901960784313, 0.9960784314, 0.6274509804, 0.0039215686, 0.7294117647058823, + 0.9960784314, 0.6196078431, 0.0039215686, 0.7333333333333333, 0.9960784314, 0.6117647059, + 0.0039215686, 0.7372549019607844, 0.9960784314, 0.6039215686, 0.0039215686, + 0.7411764705882353, 0.9960784314, 0.5960784314, 0.0039215686, 0.7450980392156863, + 0.9960784314, 0.5882352941, 0.0039215686, 0.7490196078431373, 0.9960784314, 0.5803921569, + 0.0039215686, 0.7529411764705882, 0.9960784314, 0.5725490196, 0.0039215686, + 0.7568627450980392, 0.9960784314, 0.5647058824, 0.0039215686, 0.7607843137254902, + 0.9960784314, 0.5568627451, 0.0039215686, 0.7647058823529411, 0.9960784314, 0.5490196078, + 0.0039215686, 0.7686274509803922, 0.9960784314, 0.5411764706, 0.0039215686, + 0.7725490196078432, 0.9960784314, 0.5333333333, 0.0039215686, 0.7764705882352941, + 0.9960784314, 0.5254901961, 0.0039215686, 0.7803921568627451, 0.9960784314, 0.5176470588, + 0.0039215686, 0.7843137254901961, 0.9960784314, 0.5098039216, 0.0039215686, 0.788235294117647, + 0.9960784314, 0.5019607843, 0.0039215686, 0.792156862745098, 0.9960784314, 0.4941176471, + 0.0039215686, 0.796078431372549, 0.9960784314, 0.4862745098, 0.0039215686, 0.8, 0.9960784314, + 0.4784313725, 0.0039215686, 0.803921568627451, 0.9960784314, 0.4705882353, 0.0039215686, + 0.807843137254902, 0.9960784314, 0.462745098, 0.0039215686, 0.8117647058823529, 0.9960784314, + 0.4549019608, 0.0039215686, 0.8156862745098039, 0.9960784314, 0.4470588235, 0.0039215686, + 0.8196078431372549, 0.9960784314, 0.4392156863, 0.0039215686, 0.8235294117647058, + 0.9960784314, 0.431372549, 0.0039215686, 0.8274509803921568, 0.9960784314, 0.4235294118, + 0.0039215686, 0.8313725490196079, 0.9960784314, 0.4156862745, 0.0039215686, + 0.8352941176470589, 0.9960784314, 0.4078431373, 0.0039215686, 0.8392156862745098, + 0.9960784314, 0.4, 0.0039215686, 0.8431372549019608, 0.9960784314, 0.3921568627, 0.0039215686, + 0.8470588235294118, 0.9960784314, 0.3843137255, 0.0039215686, 0.8509803921568627, + 0.9960784314, 0.3764705882, 0.0039215686, 0.8549019607843137, 0.9960784314, 0.368627451, + 0.0039215686, 0.8588235294117647, 0.9960784314, 0.3607843137, 0.0039215686, + 0.8627450980392157, 0.9960784314, 0.3529411765, 0.0039215686, 0.8666666666666667, + 0.9960784314, 0.3450980392, 0.0039215686, 0.8705882352941177, 0.9960784314, 0.337254902, + 0.0039215686, 0.8745098039215686, 0.9960784314, 0.3294117647, 0.0039215686, + 0.8784313725490196, 0.9960784314, 0.3215686275, 0.0039215686, 0.8823529411764706, + 0.9960784314, 0.3137254902, 0.0039215686, 0.8862745098039215, 0.9960784314, 0.3058823529, + 0.0039215686, 0.8901960784313725, 0.9960784314, 0.2980392157, 0.0039215686, + 0.8941176470588236, 0.9960784314, 0.2901960784, 0.0039215686, 0.8980392156862745, + 0.9960784314, 0.2823529412, 0.0039215686, 0.9019607843137255, 0.9960784314, 0.2705882353, + 0.0039215686, 0.9058823529411765, 0.9960784314, 0.2588235294, 0.0039215686, + 0.9098039215686274, 0.9960784314, 0.2509803922, 0.0039215686, 0.9137254901960784, + 0.9960784314, 0.2431372549, 0.0039215686, 0.9176470588235294, 0.9960784314, 0.231372549, + 0.0039215686, 0.9215686274509803, 0.9960784314, 0.2196078431, 0.0039215686, + 0.9254901960784314, 0.9960784314, 0.2117647059, 0.0039215686, 0.9294117647058824, + 0.9960784314, 0.2, 0.0039215686, 0.9333333333333333, 0.9960784314, 0.1882352941, 0.0039215686, + 0.9372549019607843, 0.9960784314, 0.1764705882, 0.0039215686, 0.9411764705882354, + 0.9960784314, 0.168627451, 0.0039215686, 0.9450980392156864, 0.9960784314, 0.1568627451, + 0.0039215686, 0.9490196078431372, 0.9960784314, 0.1450980392, 0.0039215686, + 0.9529411764705882, 0.9960784314, 0.1333333333, 0.0039215686, 0.9568627450980394, + 0.9960784314, 0.1254901961, 0.0039215686, 0.9607843137254903, 0.9960784314, 0.1137254902, + 0.0039215686, 0.9647058823529413, 0.9960784314, 0.1019607843, 0.0039215686, + 0.9686274509803922, 0.9960784314, 0.0901960784, 0.0039215686, 0.9725490196078431, + 0.9960784314, 0.0823529412, 0.0039215686, 0.9764705882352941, 0.9960784314, 0.0705882353, + 0.0039215686, 0.9803921568627451, 0.9960784314, 0.0588235294, 0.0039215686, 0.984313725490196, + 0.9960784314, 0.0470588235, 0.0039215686, 0.9882352941176471, 0.9960784314, 0.0392156863, + 0.0039215686, 0.9921568627450981, 0.9960784314, 0.0274509804, 0.0039215686, 0.996078431372549, + 0.9960784314, 0.0156862745, 0.0039215686, 1.0, 0.9960784314, 0.0156862745, 0.0039215686, + ], + description: 'S PET', + }, + { + ColorSpace: 'RGB', + Name: 'perfusion', + name: 'perfusion', + RGBPoints: [ + 0.0, 0.0, 0.0, 0.0, 0.00392156862745098, 0.0078431373, 0.0235294118, 0.0235294118, + 0.00784313725490196, 0.0078431373, 0.031372549, 0.0470588235, 0.011764705882352941, + 0.0078431373, 0.0392156863, 0.062745098, 0.01568627450980392, 0.0078431373, 0.0470588235, + 0.0862745098, 0.0196078431372549, 0.0078431373, 0.0549019608, 0.1019607843, + 0.023529411764705882, 0.0078431373, 0.0549019608, 0.1254901961, 0.027450980392156862, + 0.0078431373, 0.062745098, 0.1411764706, 0.03137254901960784, 0.0078431373, 0.0705882353, + 0.1647058824, 0.03529411764705882, 0.0078431373, 0.0784313725, 0.1803921569, + 0.0392156862745098, 0.0078431373, 0.0862745098, 0.2039215686, 0.043137254901960784, + 0.0078431373, 0.0862745098, 0.2196078431, 0.047058823529411764, 0.0078431373, 0.0941176471, + 0.2431372549, 0.050980392156862744, 0.0078431373, 0.1019607843, 0.2666666667, + 0.054901960784313725, 0.0078431373, 0.1098039216, 0.2823529412, 0.05882352941176471, + 0.0078431373, 0.1176470588, 0.3058823529, 0.06274509803921569, 0.0078431373, 0.1176470588, + 0.3215686275, 0.06666666666666667, 0.0078431373, 0.1254901961, 0.3450980392, + 0.07058823529411765, 0.0078431373, 0.1333333333, 0.3607843137, 0.07450980392156863, + 0.0078431373, 0.1411764706, 0.3843137255, 0.0784313725490196, 0.0078431373, 0.1490196078, 0.4, + 0.08235294117647059, 0.0078431373, 0.1490196078, 0.4235294118, 0.08627450980392157, + 0.0078431373, 0.1568627451, 0.4392156863, 0.09019607843137255, 0.0078431373, 0.1647058824, + 0.462745098, 0.09411764705882353, 0.0078431373, 0.1725490196, 0.4784313725, + 0.09803921568627451, 0.0078431373, 0.1803921569, 0.5019607843, 0.10196078431372549, + 0.0078431373, 0.1803921569, 0.5254901961, 0.10588235294117647, 0.0078431373, 0.1882352941, + 0.5411764706, 0.10980392156862745, 0.0078431373, 0.1960784314, 0.5647058824, + 0.11372549019607843, 0.0078431373, 0.2039215686, 0.5803921569, 0.11764705882352942, + 0.0078431373, 0.2117647059, 0.6039215686, 0.12156862745098039, 0.0078431373, 0.2117647059, + 0.6196078431, 0.12549019607843137, 0.0078431373, 0.2196078431, 0.6431372549, + 0.12941176470588237, 0.0078431373, 0.2274509804, 0.6588235294, 0.13333333333333333, + 0.0078431373, 0.2352941176, 0.6823529412, 0.13725490196078433, 0.0078431373, 0.2431372549, + 0.6980392157, 0.1411764705882353, 0.0078431373, 0.2431372549, 0.7215686275, + 0.1450980392156863, 0.0078431373, 0.2509803922, 0.737254902, 0.14901960784313725, + 0.0078431373, 0.2588235294, 0.7607843137, 0.15294117647058825, 0.0078431373, 0.2666666667, + 0.7843137255, 0.1568627450980392, 0.0078431373, 0.2745098039, 0.8, 0.1607843137254902, + 0.0078431373, 0.2745098039, 0.8235294118, 0.16470588235294117, 0.0078431373, 0.2823529412, + 0.8392156863, 0.16862745098039217, 0.0078431373, 0.2901960784, 0.862745098, + 0.17254901960784313, 0.0078431373, 0.2980392157, 0.8784313725, 0.17647058823529413, + 0.0078431373, 0.3058823529, 0.9019607843, 0.1803921568627451, 0.0078431373, 0.3058823529, + 0.9176470588, 0.1843137254901961, 0.0078431373, 0.2980392157, 0.9411764706, + 0.18823529411764706, 0.0078431373, 0.3058823529, 0.9568627451, 0.19215686274509805, + 0.0078431373, 0.2980392157, 0.9803921569, 0.19607843137254902, 0.0078431373, 0.2980392157, + 0.9882352941, 0.2, 0.0078431373, 0.2901960784, 0.9803921569, 0.20392156862745098, + 0.0078431373, 0.2901960784, 0.9647058824, 0.20784313725490197, 0.0078431373, 0.2823529412, + 0.9568627451, 0.21176470588235294, 0.0078431373, 0.2823529412, 0.9411764706, + 0.21568627450980393, 0.0078431373, 0.2745098039, 0.9333333333, 0.2196078431372549, + 0.0078431373, 0.2666666667, 0.9176470588, 0.2235294117647059, 0.0078431373, 0.2666666667, + 0.9098039216, 0.22745098039215686, 0.0078431373, 0.2588235294, 0.9019607843, + 0.23137254901960785, 0.0078431373, 0.2588235294, 0.8862745098, 0.23529411764705885, + 0.0078431373, 0.2509803922, 0.8784313725, 0.23921568627450984, 0.0078431373, 0.2509803922, + 0.862745098, 0.24313725490196078, 0.0078431373, 0.2431372549, 0.8549019608, + 0.24705882352941178, 0.0078431373, 0.2352941176, 0.8392156863, 0.25098039215686274, + 0.0078431373, 0.2352941176, 0.831372549, 0.2549019607843137, 0.0078431373, 0.2274509804, + 0.8235294118, 0.25882352941176473, 0.0078431373, 0.2274509804, 0.8078431373, + 0.2627450980392157, 0.0078431373, 0.2196078431, 0.8, 0.26666666666666666, 0.0078431373, + 0.2196078431, 0.7843137255, 0.27058823529411763, 0.0078431373, 0.2117647059, 0.7764705882, + 0.27450980392156865, 0.0078431373, 0.2039215686, 0.7607843137, 0.2784313725490196, + 0.0078431373, 0.2039215686, 0.7529411765, 0.2823529411764706, 0.0078431373, 0.1960784314, + 0.7450980392, 0.28627450980392155, 0.0078431373, 0.1960784314, 0.7294117647, + 0.2901960784313726, 0.0078431373, 0.1882352941, 0.7215686275, 0.29411764705882354, + 0.0078431373, 0.1882352941, 0.7058823529, 0.2980392156862745, 0.0078431373, 0.1803921569, + 0.6980392157, 0.30196078431372547, 0.0078431373, 0.1803921569, 0.6823529412, + 0.3058823529411765, 0.0078431373, 0.1725490196, 0.6745098039, 0.30980392156862746, + 0.0078431373, 0.1647058824, 0.6666666667, 0.3137254901960784, 0.0078431373, 0.1647058824, + 0.6509803922, 0.3176470588235294, 0.0078431373, 0.1568627451, 0.6431372549, + 0.3215686274509804, 0.0078431373, 0.1568627451, 0.6274509804, 0.3254901960784314, + 0.0078431373, 0.1490196078, 0.6196078431, 0.32941176470588235, 0.0078431373, 0.1490196078, + 0.6039215686, 0.3333333333333333, 0.0078431373, 0.1411764706, 0.5960784314, + 0.33725490196078434, 0.0078431373, 0.1333333333, 0.5882352941, 0.3411764705882353, + 0.0078431373, 0.1333333333, 0.5725490196, 0.34509803921568627, 0.0078431373, 0.1254901961, + 0.5647058824, 0.34901960784313724, 0.0078431373, 0.1254901961, 0.5490196078, + 0.35294117647058826, 0.0078431373, 0.1176470588, 0.5411764706, 0.3568627450980392, + 0.0078431373, 0.1176470588, 0.5254901961, 0.3607843137254902, 0.0078431373, 0.1098039216, + 0.5176470588, 0.36470588235294116, 0.0078431373, 0.1019607843, 0.5098039216, + 0.3686274509803922, 0.0078431373, 0.1019607843, 0.4941176471, 0.37254901960784315, + 0.0078431373, 0.0941176471, 0.4862745098, 0.3764705882352941, 0.0078431373, 0.0941176471, + 0.4705882353, 0.3803921568627451, 0.0078431373, 0.0862745098, 0.462745098, 0.3843137254901961, + 0.0078431373, 0.0862745098, 0.4470588235, 0.38823529411764707, 0.0078431373, 0.0784313725, + 0.4392156863, 0.39215686274509803, 0.0078431373, 0.0705882353, 0.431372549, 0.396078431372549, + 0.0078431373, 0.0705882353, 0.4156862745, 0.4, 0.0078431373, 0.062745098, 0.4078431373, + 0.403921568627451, 0.0078431373, 0.062745098, 0.3921568627, 0.40784313725490196, 0.0078431373, + 0.0549019608, 0.3843137255, 0.4117647058823529, 0.0078431373, 0.0549019608, 0.368627451, + 0.41568627450980394, 0.0078431373, 0.0470588235, 0.3607843137, 0.4196078431372549, + 0.0078431373, 0.0470588235, 0.3529411765, 0.4235294117647059, 0.0078431373, 0.0392156863, + 0.337254902, 0.42745098039215684, 0.0078431373, 0.031372549, 0.3294117647, + 0.43137254901960786, 0.0078431373, 0.031372549, 0.3137254902, 0.43529411764705883, + 0.0078431373, 0.0235294118, 0.3058823529, 0.4392156862745098, 0.0078431373, 0.0235294118, + 0.2901960784, 0.44313725490196076, 0.0078431373, 0.0156862745, 0.2823529412, + 0.4470588235294118, 0.0078431373, 0.0156862745, 0.2745098039, 0.45098039215686275, + 0.0078431373, 0.0078431373, 0.2588235294, 0.4549019607843137, 0.0235294118, 0.0078431373, + 0.2509803922, 0.4588235294117647, 0.0078431373, 0.0078431373, 0.2352941176, + 0.4627450980392157, 0.0078431373, 0.0078431373, 0.2274509804, 0.4666666666666667, + 0.0078431373, 0.0078431373, 0.2117647059, 0.4705882352941177, 0.0078431373, 0.0078431373, + 0.2039215686, 0.4745098039215686, 0.0078431373, 0.0078431373, 0.1960784314, + 0.4784313725490197, 0.0078431373, 0.0078431373, 0.1803921569, 0.48235294117647065, + 0.0078431373, 0.0078431373, 0.1725490196, 0.48627450980392156, 0.0078431373, 0.0078431373, + 0.1568627451, 0.49019607843137253, 0.0078431373, 0.0078431373, 0.1490196078, + 0.49411764705882355, 0.0078431373, 0.0078431373, 0.1333333333, 0.4980392156862745, + 0.0078431373, 0.0078431373, 0.1254901961, 0.5019607843137255, 0.0078431373, 0.0078431373, + 0.1176470588, 0.5058823529411764, 0.0078431373, 0.0078431373, 0.1019607843, + 0.5098039215686274, 0.0078431373, 0.0078431373, 0.0941176471, 0.5137254901960784, + 0.0078431373, 0.0078431373, 0.0784313725, 0.5176470588235295, 0.0078431373, 0.0078431373, + 0.0705882353, 0.5215686274509804, 0.0078431373, 0.0078431373, 0.0549019608, + 0.5254901960784314, 0.0078431373, 0.0078431373, 0.0470588235, 0.5294117647058824, + 0.0235294118, 0.0078431373, 0.0392156863, 0.5333333333333333, 0.031372549, 0.0078431373, + 0.0235294118, 0.5372549019607843, 0.0392156863, 0.0078431373, 0.0156862745, + 0.5411764705882353, 0.0549019608, 0.0078431373, 0.0, 0.5450980392156862, 0.062745098, + 0.0078431373, 0.0, 0.5490196078431373, 0.0705882353, 0.0078431373, 0.0, 0.5529411764705883, + 0.0862745098, 0.0078431373, 0.0, 0.5568627450980392, 0.0941176471, 0.0078431373, 0.0, + 0.5607843137254902, 0.1019607843, 0.0078431373, 0.0, 0.5647058823529412, 0.1098039216, + 0.0078431373, 0.0, 0.5686274509803921, 0.1254901961, 0.0078431373, 0.0, 0.5725490196078431, + 0.1333333333, 0.0078431373, 0.0, 0.5764705882352941, 0.1411764706, 0.0078431373, 0.0, + 0.5803921568627451, 0.1568627451, 0.0078431373, 0.0, 0.5843137254901961, 0.1647058824, + 0.0078431373, 0.0, 0.5882352941176471, 0.1725490196, 0.0078431373, 0.0, 0.592156862745098, + 0.1882352941, 0.0078431373, 0.0, 0.596078431372549, 0.1960784314, 0.0078431373, 0.0, 0.6, + 0.2039215686, 0.0078431373, 0.0, 0.6039215686274509, 0.2117647059, 0.0078431373, 0.0, + 0.6078431372549019, 0.2274509804, 0.0078431373, 0.0, 0.611764705882353, 0.2352941176, + 0.0078431373, 0.0, 0.615686274509804, 0.2431372549, 0.0078431373, 0.0, 0.6196078431372549, + 0.2588235294, 0.0078431373, 0.0, 0.6235294117647059, 0.2666666667, 0.0078431373, 0.0, + 0.6274509803921569, 0.2745098039, 0.0, 0.0, 0.6313725490196078, 0.2901960784, 0.0156862745, + 0.0, 0.6352941176470588, 0.2980392157, 0.0235294118, 0.0, 0.6392156862745098, 0.3058823529, + 0.0392156863, 0.0, 0.6431372549019608, 0.3137254902, 0.0470588235, 0.0, 0.6470588235294118, + 0.3294117647, 0.0549019608, 0.0, 0.6509803921568628, 0.337254902, 0.0705882353, 0.0, + 0.6549019607843137, 0.3450980392, 0.0784313725, 0.0, 0.6588235294117647, 0.3607843137, + 0.0862745098, 0.0, 0.6627450980392157, 0.368627451, 0.1019607843, 0.0, 0.6666666666666666, + 0.3764705882, 0.1098039216, 0.0, 0.6705882352941176, 0.3843137255, 0.1176470588, 0.0, + 0.6745098039215687, 0.4, 0.1333333333, 0.0, 0.6784313725490196, 0.4078431373, 0.1411764706, + 0.0, 0.6823529411764706, 0.4156862745, 0.1490196078, 0.0, 0.6862745098039216, 0.431372549, + 0.1647058824, 0.0, 0.6901960784313725, 0.4392156863, 0.1725490196, 0.0, 0.6941176470588235, + 0.4470588235, 0.1803921569, 0.0, 0.6980392156862745, 0.462745098, 0.1960784314, 0.0, + 0.7019607843137254, 0.4705882353, 0.2039215686, 0.0, 0.7058823529411765, 0.4784313725, + 0.2117647059, 0.0, 0.7098039215686275, 0.4862745098, 0.2274509804, 0.0, 0.7137254901960784, + 0.5019607843, 0.2352941176, 0.0, 0.7176470588235294, 0.5098039216, 0.2431372549, 0.0, + 0.7215686274509804, 0.5176470588, 0.2588235294, 0.0, 0.7254901960784313, 0.5333333333, + 0.2666666667, 0.0, 0.7294117647058823, 0.5411764706, 0.2745098039, 0.0, 0.7333333333333333, + 0.5490196078, 0.2901960784, 0.0, 0.7372549019607844, 0.5647058824, 0.2980392157, 0.0, + 0.7411764705882353, 0.5725490196, 0.3058823529, 0.0, 0.7450980392156863, 0.5803921569, + 0.3215686275, 0.0, 0.7490196078431373, 0.5882352941, 0.3294117647, 0.0, 0.7529411764705882, + 0.6039215686, 0.337254902, 0.0, 0.7568627450980392, 0.6117647059, 0.3529411765, 0.0, + 0.7607843137254902, 0.6196078431, 0.3607843137, 0.0, 0.7647058823529411, 0.6352941176, + 0.368627451, 0.0, 0.7686274509803922, 0.6431372549, 0.3843137255, 0.0, 0.7725490196078432, + 0.6509803922, 0.3921568627, 0.0, 0.7764705882352941, 0.6588235294, 0.4, 0.0, + 0.7803921568627451, 0.6745098039, 0.4156862745, 0.0, 0.7843137254901961, 0.6823529412, + 0.4235294118, 0.0, 0.788235294117647, 0.6901960784, 0.431372549, 0.0, 0.792156862745098, + 0.7058823529, 0.4470588235, 0.0, 0.796078431372549, 0.7137254902, 0.4549019608, 0.0, 0.8, + 0.7215686275, 0.462745098, 0.0, 0.803921568627451, 0.737254902, 0.4784313725, 0.0, + 0.807843137254902, 0.7450980392, 0.4862745098, 0.0, 0.8117647058823529, 0.7529411765, + 0.4941176471, 0.0, 0.8156862745098039, 0.7607843137, 0.5098039216, 0.0, 0.8196078431372549, + 0.7764705882, 0.5176470588, 0.0, 0.8235294117647058, 0.7843137255, 0.5254901961, 0.0, + 0.8274509803921568, 0.7921568627, 0.5411764706, 0.0, 0.8313725490196079, 0.8078431373, + 0.5490196078, 0.0, 0.8352941176470589, 0.8156862745, 0.5568627451, 0.0, 0.8392156862745098, + 0.8235294118, 0.5725490196, 0.0, 0.8431372549019608, 0.8392156863, 0.5803921569, 0.0, + 0.8470588235294118, 0.8470588235, 0.5882352941, 0.0, 0.8509803921568627, 0.8549019608, + 0.6039215686, 0.0, 0.8549019607843137, 0.862745098, 0.6117647059, 0.0, 0.8588235294117647, + 0.8784313725, 0.6196078431, 0.0, 0.8627450980392157, 0.8862745098, 0.6352941176, 0.0, + 0.8666666666666667, 0.8941176471, 0.6431372549, 0.0, 0.8705882352941177, 0.9098039216, + 0.6509803922, 0.0, 0.8745098039215686, 0.9176470588, 0.6666666667, 0.0, 0.8784313725490196, + 0.9254901961, 0.6745098039, 0.0, 0.8823529411764706, 0.9411764706, 0.6823529412, 0.0, + 0.8862745098039215, 0.9490196078, 0.6980392157, 0.0, 0.8901960784313725, 0.9568627451, + 0.7058823529, 0.0, 0.8941176470588236, 0.9647058824, 0.7137254902, 0.0, 0.8980392156862745, + 0.9803921569, 0.7294117647, 0.0, 0.9019607843137255, 0.9882352941, 0.737254902, 0.0, + 0.9058823529411765, 0.9960784314, 0.7450980392, 0.0, 0.9098039215686274, 0.9960784314, + 0.7607843137, 0.0, 0.9137254901960784, 0.9960784314, 0.768627451, 0.0, 0.9176470588235294, + 0.9960784314, 0.7764705882, 0.0, 0.9215686274509803, 0.9960784314, 0.7921568627, 0.0, + 0.9254901960784314, 0.9960784314, 0.8, 0.0, 0.9294117647058824, 0.9960784314, 0.8078431373, + 0.0, 0.9333333333333333, 0.9960784314, 0.8235294118, 0.0, 0.9372549019607843, 0.9960784314, + 0.831372549, 0.0, 0.9411764705882354, 0.9960784314, 0.8392156863, 0.0, 0.9450980392156864, + 0.9960784314, 0.8549019608, 0.0, 0.9490196078431372, 0.9960784314, 0.862745098, 0.0549019608, + 0.9529411764705882, 0.9960784314, 0.8705882353, 0.1098039216, 0.9568627450980394, + 0.9960784314, 0.8862745098, 0.1647058824, 0.9607843137254903, 0.9960784314, 0.8941176471, + 0.2196078431, 0.9647058823529413, 0.9960784314, 0.9019607843, 0.2666666667, + 0.9686274509803922, 0.9960784314, 0.9176470588, 0.3215686275, 0.9725490196078431, + 0.9960784314, 0.9254901961, 0.3764705882, 0.9764705882352941, 0.9960784314, 0.9333333333, + 0.431372549, 0.9803921568627451, 0.9960784314, 0.9490196078, 0.4862745098, 0.984313725490196, + 0.9960784314, 0.9568627451, 0.5333333333, 0.9882352941176471, 0.9960784314, 0.9647058824, + 0.5882352941, 0.9921568627450981, 0.9960784314, 0.9803921569, 0.6431372549, 0.996078431372549, + 0.9960784314, 0.9882352941, 0.6980392157, 1.0, 0.9960784314, 0.9960784314, 0.7450980392, + ], + description: 'Perfusion', + }, + { + ColorSpace: 'RGB', + Name: 'rainbow_2', + name: 'rainbow_2', + RGBPoints: [ + 0.0, 0.0, 0.0, 0.0, 0.00392156862745098, 0.0156862745, 0.0, 0.0117647059, 0.00784313725490196, + 0.0352941176, 0.0, 0.0274509804, 0.011764705882352941, 0.0509803922, 0.0, 0.0392156863, + 0.01568627450980392, 0.0705882353, 0.0, 0.0549019608, 0.0196078431372549, 0.0862745098, 0.0, + 0.0745098039, 0.023529411764705882, 0.1058823529, 0.0, 0.0901960784, 0.027450980392156862, + 0.1215686275, 0.0, 0.1098039216, 0.03137254901960784, 0.1411764706, 0.0, 0.1254901961, + 0.03529411764705882, 0.1568627451, 0.0, 0.1490196078, 0.0392156862745098, 0.1764705882, 0.0, + 0.168627451, 0.043137254901960784, 0.1960784314, 0.0, 0.1882352941, 0.047058823529411764, + 0.2117647059, 0.0, 0.2078431373, 0.050980392156862744, 0.2274509804, 0.0, 0.231372549, + 0.054901960784313725, 0.2392156863, 0.0, 0.2470588235, 0.05882352941176471, 0.2509803922, 0.0, + 0.2666666667, 0.06274509803921569, 0.2666666667, 0.0, 0.2823529412, 0.06666666666666667, + 0.2705882353, 0.0, 0.3019607843, 0.07058823529411765, 0.2823529412, 0.0, 0.3176470588, + 0.07450980392156863, 0.2901960784, 0.0, 0.337254902, 0.0784313725490196, 0.3019607843, 0.0, + 0.3568627451, 0.08235294117647059, 0.3098039216, 0.0, 0.3725490196, 0.08627450980392157, + 0.3137254902, 0.0, 0.3921568627, 0.09019607843137255, 0.3215686275, 0.0, 0.4078431373, + 0.09411764705882353, 0.3254901961, 0.0, 0.4274509804, 0.09803921568627451, 0.3333333333, 0.0, + 0.4431372549, 0.10196078431372549, 0.3294117647, 0.0, 0.462745098, 0.10588235294117647, + 0.337254902, 0.0, 0.4784313725, 0.10980392156862745, 0.3411764706, 0.0, 0.4980392157, + 0.11372549019607843, 0.3450980392, 0.0, 0.5176470588, 0.11764705882352942, 0.337254902, 0.0, + 0.5333333333, 0.12156862745098039, 0.3411764706, 0.0, 0.5529411765, 0.12549019607843137, + 0.3411764706, 0.0, 0.568627451, 0.12941176470588237, 0.3411764706, 0.0, 0.5882352941, + 0.13333333333333333, 0.3333333333, 0.0, 0.6039215686, 0.13725490196078433, 0.3294117647, 0.0, + 0.6235294118, 0.1411764705882353, 0.3294117647, 0.0, 0.6392156863, 0.1450980392156863, + 0.3294117647, 0.0, 0.6588235294, 0.14901960784313725, 0.3254901961, 0.0, 0.6784313725, + 0.15294117647058825, 0.3098039216, 0.0, 0.6941176471, 0.1568627450980392, 0.3058823529, 0.0, + 0.7137254902, 0.1607843137254902, 0.3019607843, 0.0, 0.7294117647, 0.16470588235294117, + 0.2980392157, 0.0, 0.7490196078, 0.16862745098039217, 0.2784313725, 0.0, 0.7647058824, + 0.17254901960784313, 0.2745098039, 0.0, 0.7843137255, 0.17647058823529413, 0.2666666667, 0.0, + 0.8, 0.1803921568627451, 0.2588235294, 0.0, 0.8196078431, 0.1843137254901961, 0.2352941176, + 0.0, 0.8392156863, 0.18823529411764706, 0.2274509804, 0.0, 0.8549019608, 0.19215686274509805, + 0.2156862745, 0.0, 0.8745098039, 0.19607843137254902, 0.2078431373, 0.0, 0.8901960784, 0.2, + 0.1803921569, 0.0, 0.9098039216, 0.20392156862745098, 0.168627451, 0.0, 0.9254901961, + 0.20784313725490197, 0.1568627451, 0.0, 0.9450980392, 0.21176470588235294, 0.1411764706, 0.0, + 0.9607843137, 0.21568627450980393, 0.1294117647, 0.0, 0.9803921569, 0.2196078431372549, + 0.0980392157, 0.0, 1.0, 0.2235294117647059, 0.0823529412, 0.0, 1.0, 0.22745098039215686, + 0.062745098, 0.0, 1.0, 0.23137254901960785, 0.0470588235, 0.0, 1.0, 0.23529411764705885, + 0.0156862745, 0.0, 1.0, 0.23921568627450984, 0.0, 0.0, 1.0, 0.24313725490196078, 0.0, + 0.0156862745, 1.0, 0.24705882352941178, 0.0, 0.031372549, 1.0, 0.25098039215686274, 0.0, + 0.062745098, 1.0, 0.2549019607843137, 0.0, 0.0823529412, 1.0, 0.25882352941176473, 0.0, + 0.0980392157, 1.0, 0.2627450980392157, 0.0, 0.1137254902, 1.0, 0.26666666666666666, 0.0, + 0.1490196078, 1.0, 0.27058823529411763, 0.0, 0.1647058824, 1.0, 0.27450980392156865, 0.0, + 0.1803921569, 1.0, 0.2784313725490196, 0.0, 0.2, 1.0, 0.2823529411764706, 0.0, 0.2156862745, + 1.0, 0.28627450980392155, 0.0, 0.2470588235, 1.0, 0.2901960784313726, 0.0, 0.262745098, 1.0, + 0.29411764705882354, 0.0, 0.2823529412, 1.0, 0.2980392156862745, 0.0, 0.2980392157, 1.0, + 0.30196078431372547, 0.0, 0.3294117647, 1.0, 0.3058823529411765, 0.0, 0.3490196078, 1.0, + 0.30980392156862746, 0.0, 0.3647058824, 1.0, 0.3137254901960784, 0.0, 0.3803921569, 1.0, + 0.3176470588235294, 0.0, 0.4156862745, 1.0, 0.3215686274509804, 0.0, 0.431372549, 1.0, + 0.3254901960784314, 0.0, 0.4470588235, 1.0, 0.32941176470588235, 0.0, 0.4666666667, 1.0, + 0.3333333333333333, 0.0, 0.4980392157, 1.0, 0.33725490196078434, 0.0, 0.5137254902, 1.0, + 0.3411764705882353, 0.0, 0.5294117647, 1.0, 0.34509803921568627, 0.0, 0.5490196078, 1.0, + 0.34901960784313724, 0.0, 0.5647058824, 1.0, 0.35294117647058826, 0.0, 0.5960784314, 1.0, + 0.3568627450980392, 0.0, 0.6156862745, 1.0, 0.3607843137254902, 0.0, 0.631372549, 1.0, + 0.36470588235294116, 0.0, 0.6470588235, 1.0, 0.3686274509803922, 0.0, 0.6823529412, 1.0, + 0.37254901960784315, 0.0, 0.6980392157, 1.0, 0.3764705882352941, 0.0, 0.7137254902, 1.0, + 0.3803921568627451, 0.0, 0.7333333333, 1.0, 0.3843137254901961, 0.0, 0.7647058824, 1.0, + 0.38823529411764707, 0.0, 0.7803921569, 1.0, 0.39215686274509803, 0.0, 0.7960784314, 1.0, + 0.396078431372549, 0.0, 0.8156862745, 1.0, 0.4, 0.0, 0.8470588235, 1.0, 0.403921568627451, + 0.0, 0.862745098, 1.0, 0.40784313725490196, 0.0, 0.8823529412, 1.0, 0.4117647058823529, 0.0, + 0.8980392157, 1.0, 0.41568627450980394, 0.0, 0.9137254902, 1.0, 0.4196078431372549, 0.0, + 0.9490196078, 1.0, 0.4235294117647059, 0.0, 0.9647058824, 1.0, 0.42745098039215684, 0.0, + 0.9803921569, 1.0, 0.43137254901960786, 0.0, 1.0, 1.0, 0.43529411764705883, 0.0, 1.0, + 0.9647058824, 0.4392156862745098, 0.0, 1.0, 0.9490196078, 0.44313725490196076, 0.0, 1.0, + 0.9333333333, 0.4470588235294118, 0.0, 1.0, 0.9137254902, 0.45098039215686275, 0.0, 1.0, + 0.8823529412, 0.4549019607843137, 0.0, 1.0, 0.862745098, 0.4588235294117647, 0.0, 1.0, + 0.8470588235, 0.4627450980392157, 0.0, 1.0, 0.831372549, 0.4666666666666667, 0.0, 1.0, + 0.7960784314, 0.4705882352941177, 0.0, 1.0, 0.7803921569, 0.4745098039215686, 0.0, 1.0, + 0.7647058824, 0.4784313725490197, 0.0, 1.0, 0.7490196078, 0.48235294117647065, 0.0, 1.0, + 0.7333333333, 0.48627450980392156, 0.0, 1.0, 0.6980392157, 0.49019607843137253, 0.0, 1.0, + 0.6823529412, 0.49411764705882355, 0.0, 1.0, 0.6666666667, 0.4980392156862745, 0.0, 1.0, + 0.6470588235, 0.5019607843137255, 0.0, 1.0, 0.6156862745, 0.5058823529411764, 0.0, 1.0, + 0.5960784314, 0.5098039215686274, 0.0, 1.0, 0.5803921569, 0.5137254901960784, 0.0, 1.0, + 0.5647058824, 0.5176470588235295, 0.0, 1.0, 0.5294117647, 0.5215686274509804, 0.0, 1.0, + 0.5137254902, 0.5254901960784314, 0.0, 1.0, 0.4980392157, 0.5294117647058824, 0.0, 1.0, + 0.4823529412, 0.5333333333333333, 0.0, 1.0, 0.4470588235, 0.5372549019607843, 0.0, 1.0, + 0.431372549, 0.5411764705882353, 0.0, 1.0, 0.4156862745, 0.5450980392156862, 0.0, 1.0, 0.4, + 0.5490196078431373, 0.0, 1.0, 0.3803921569, 0.5529411764705883, 0.0, 1.0, 0.3490196078, + 0.5568627450980392, 0.0, 1.0, 0.3294117647, 0.5607843137254902, 0.0, 1.0, 0.3137254902, + 0.5647058823529412, 0.0, 1.0, 0.2980392157, 0.5686274509803921, 0.0, 1.0, 0.262745098, + 0.5725490196078431, 0.0, 1.0, 0.2470588235, 0.5764705882352941, 0.0, 1.0, 0.231372549, + 0.5803921568627451, 0.0, 1.0, 0.2156862745, 0.5843137254901961, 0.0, 1.0, 0.1803921569, + 0.5882352941176471, 0.0, 1.0, 0.1647058824, 0.592156862745098, 0.0, 1.0, 0.1490196078, + 0.596078431372549, 0.0, 1.0, 0.1333333333, 0.6, 0.0, 1.0, 0.0980392157, 0.6039215686274509, + 0.0, 1.0, 0.0823529412, 0.6078431372549019, 0.0, 1.0, 0.062745098, 0.611764705882353, 0.0, + 1.0, 0.0470588235, 0.615686274509804, 0.0, 1.0, 0.031372549, 0.6196078431372549, 0.0, 1.0, + 0.0, 0.6235294117647059, 0.0156862745, 1.0, 0.0, 0.6274509803921569, 0.031372549, 1.0, 0.0, + 0.6313725490196078, 0.0470588235, 1.0, 0.0, 0.6352941176470588, 0.0823529412, 1.0, 0.0, + 0.6392156862745098, 0.0980392157, 1.0, 0.0, 0.6431372549019608, 0.1137254902, 1.0, 0.0, + 0.6470588235294118, 0.1294117647, 1.0, 0.0, 0.6509803921568628, 0.1647058824, 1.0, 0.0, + 0.6549019607843137, 0.1803921569, 1.0, 0.0, 0.6588235294117647, 0.2, 1.0, 0.0, + 0.6627450980392157, 0.2156862745, 1.0, 0.0, 0.6666666666666666, 0.2470588235, 1.0, 0.0, + 0.6705882352941176, 0.262745098, 1.0, 0.0, 0.6745098039215687, 0.2823529412, 1.0, 0.0, + 0.6784313725490196, 0.2980392157, 1.0, 0.0, 0.6823529411764706, 0.3137254902, 1.0, 0.0, + 0.6862745098039216, 0.3490196078, 1.0, 0.0, 0.6901960784313725, 0.3647058824, 1.0, 0.0, + 0.6941176470588235, 0.3803921569, 1.0, 0.0, 0.6980392156862745, 0.3960784314, 1.0, 0.0, + 0.7019607843137254, 0.431372549, 1.0, 0.0, 0.7058823529411765, 0.4470588235, 1.0, 0.0, + 0.7098039215686275, 0.4666666667, 1.0, 0.0, 0.7137254901960784, 0.4823529412, 1.0, 0.0, + 0.7176470588235294, 0.5137254902, 1.0, 0.0, 0.7215686274509804, 0.5294117647, 1.0, 0.0, + 0.7254901960784313, 0.5490196078, 1.0, 0.0, 0.7294117647058823, 0.5647058824, 1.0, 0.0, + 0.7333333333333333, 0.6, 1.0, 0.0, 0.7372549019607844, 0.6156862745, 1.0, 0.0, + 0.7411764705882353, 0.631372549, 1.0, 0.0, 0.7450980392156863, 0.6470588235, 1.0, 0.0, + 0.7490196078431373, 0.662745098, 1.0, 0.0, 0.7529411764705882, 0.6980392157, 1.0, 0.0, + 0.7568627450980392, 0.7137254902, 1.0, 0.0, 0.7607843137254902, 0.7333333333, 1.0, 0.0, + 0.7647058823529411, 0.7490196078, 1.0, 0.0, 0.7686274509803922, 0.7803921569, 1.0, 0.0, + 0.7725490196078432, 0.7960784314, 1.0, 0.0, 0.7764705882352941, 0.8156862745, 1.0, 0.0, + 0.7803921568627451, 0.831372549, 1.0, 0.0, 0.7843137254901961, 0.8666666667, 1.0, 0.0, + 0.788235294117647, 0.8823529412, 1.0, 0.0, 0.792156862745098, 0.8980392157, 1.0, 0.0, + 0.796078431372549, 0.9137254902, 1.0, 0.0, 0.8, 0.9490196078, 1.0, 0.0, 0.803921568627451, + 0.9647058824, 1.0, 0.0, 0.807843137254902, 0.9803921569, 1.0, 0.0, 0.8117647058823529, 1.0, + 1.0, 0.0, 0.8156862745098039, 1.0, 0.9803921569, 0.0, 0.8196078431372549, 1.0, 0.9490196078, + 0.0, 0.8235294117647058, 1.0, 0.9333333333, 0.0, 0.8274509803921568, 1.0, 0.9137254902, 0.0, + 0.8313725490196079, 1.0, 0.8980392157, 0.0, 0.8352941176470589, 1.0, 0.8666666667, 0.0, + 0.8392156862745098, 1.0, 0.8470588235, 0.0, 0.8431372549019608, 1.0, 0.831372549, 0.0, + 0.8470588235294118, 1.0, 0.8156862745, 0.0, 0.8509803921568627, 1.0, 0.7803921569, 0.0, + 0.8549019607843137, 1.0, 0.7647058824, 0.0, 0.8588235294117647, 1.0, 0.7490196078, 0.0, + 0.8627450980392157, 1.0, 0.7333333333, 0.0, 0.8666666666666667, 1.0, 0.6980392157, 0.0, + 0.8705882352941177, 1.0, 0.6823529412, 0.0, 0.8745098039215686, 1.0, 0.6666666667, 0.0, + 0.8784313725490196, 1.0, 0.6470588235, 0.0, 0.8823529411764706, 1.0, 0.631372549, 0.0, + 0.8862745098039215, 1.0, 0.6, 0.0, 0.8901960784313725, 1.0, 0.5803921569, 0.0, + 0.8941176470588236, 1.0, 0.5647058824, 0.0, 0.8980392156862745, 1.0, 0.5490196078, 0.0, + 0.9019607843137255, 1.0, 0.5137254902, 0.0, 0.9058823529411765, 1.0, 0.4980392157, 0.0, + 0.9098039215686274, 1.0, 0.4823529412, 0.0, 0.9137254901960784, 1.0, 0.4666666667, 0.0, + 0.9176470588235294, 1.0, 0.431372549, 0.0, 0.9215686274509803, 1.0, 0.4156862745, 0.0, + 0.9254901960784314, 1.0, 0.4, 0.0, 0.9294117647058824, 1.0, 0.3803921569, 0.0, + 0.9333333333333333, 1.0, 0.3490196078, 0.0, 0.9372549019607843, 1.0, 0.3333333333, 0.0, + 0.9411764705882354, 1.0, 0.3137254902, 0.0, 0.9450980392156864, 1.0, 0.2980392157, 0.0, + 0.9490196078431372, 1.0, 0.2823529412, 0.0, 0.9529411764705882, 1.0, 0.2470588235, 0.0, + 0.9568627450980394, 1.0, 0.231372549, 0.0, 0.9607843137254903, 1.0, 0.2156862745, 0.0, + 0.9647058823529413, 1.0, 0.2, 0.0, 0.9686274509803922, 1.0, 0.1647058824, 0.0, + 0.9725490196078431, 1.0, 0.1490196078, 0.0, 0.9764705882352941, 1.0, 0.1333333333, 0.0, + 0.9803921568627451, 1.0, 0.1137254902, 0.0, 0.984313725490196, 1.0, 0.0823529412, 0.0, + 0.9882352941176471, 1.0, 0.0666666667, 0.0, 0.9921568627450981, 1.0, 0.0470588235, 0.0, + 0.996078431372549, 1.0, 0.031372549, 0.0, 1.0, 1.0, 0.0, 0.0, + ], + description: 'Rainbow', + }, + { + ColorSpace: 'RGB', + Name: 'suv', + name: 'suv', + RGBPoints: [ + 0.0, 1.0, 1.0, 1.0, 0.00392156862745098, 1.0, 1.0, 1.0, 0.00784313725490196, 1.0, 1.0, 1.0, + 0.011764705882352941, 1.0, 1.0, 1.0, 0.01568627450980392, 1.0, 1.0, 1.0, 0.0196078431372549, + 1.0, 1.0, 1.0, 0.023529411764705882, 1.0, 1.0, 1.0, 0.027450980392156862, 1.0, 1.0, 1.0, + 0.03137254901960784, 1.0, 1.0, 1.0, 0.03529411764705882, 1.0, 1.0, 1.0, 0.0392156862745098, + 1.0, 1.0, 1.0, 0.043137254901960784, 1.0, 1.0, 1.0, 0.047058823529411764, 1.0, 1.0, 1.0, + 0.050980392156862744, 1.0, 1.0, 1.0, 0.054901960784313725, 1.0, 1.0, 1.0, 0.05882352941176471, + 1.0, 1.0, 1.0, 0.06274509803921569, 1.0, 1.0, 1.0, 0.06666666666666667, 1.0, 1.0, 1.0, + 0.07058823529411765, 1.0, 1.0, 1.0, 0.07450980392156863, 1.0, 1.0, 1.0, 0.0784313725490196, + 1.0, 1.0, 1.0, 0.08235294117647059, 1.0, 1.0, 1.0, 0.08627450980392157, 1.0, 1.0, 1.0, + 0.09019607843137255, 1.0, 1.0, 1.0, 0.09411764705882353, 1.0, 1.0, 1.0, 0.09803921568627451, + 1.0, 1.0, 1.0, 0.10196078431372549, 0.737254902, 0.737254902, 0.737254902, + 0.10588235294117647, 0.737254902, 0.737254902, 0.737254902, 0.10980392156862745, 0.737254902, + 0.737254902, 0.737254902, 0.11372549019607843, 0.737254902, 0.737254902, 0.737254902, + 0.11764705882352942, 0.737254902, 0.737254902, 0.737254902, 0.12156862745098039, 0.737254902, + 0.737254902, 0.737254902, 0.12549019607843137, 0.737254902, 0.737254902, 0.737254902, + 0.12941176470588237, 0.737254902, 0.737254902, 0.737254902, 0.13333333333333333, 0.737254902, + 0.737254902, 0.737254902, 0.13725490196078433, 0.737254902, 0.737254902, 0.737254902, + 0.1411764705882353, 0.737254902, 0.737254902, 0.737254902, 0.1450980392156863, 0.737254902, + 0.737254902, 0.737254902, 0.14901960784313725, 0.737254902, 0.737254902, 0.737254902, + 0.15294117647058825, 0.737254902, 0.737254902, 0.737254902, 0.1568627450980392, 0.737254902, + 0.737254902, 0.737254902, 0.1607843137254902, 0.737254902, 0.737254902, 0.737254902, + 0.16470588235294117, 0.737254902, 0.737254902, 0.737254902, 0.16862745098039217, 0.737254902, + 0.737254902, 0.737254902, 0.17254901960784313, 0.737254902, 0.737254902, 0.737254902, + 0.17647058823529413, 0.737254902, 0.737254902, 0.737254902, 0.1803921568627451, 0.737254902, + 0.737254902, 0.737254902, 0.1843137254901961, 0.737254902, 0.737254902, 0.737254902, + 0.18823529411764706, 0.737254902, 0.737254902, 0.737254902, 0.19215686274509805, 0.737254902, + 0.737254902, 0.737254902, 0.19607843137254902, 0.737254902, 0.737254902, 0.737254902, 0.2, + 0.737254902, 0.737254902, 0.737254902, 0.20392156862745098, 0.431372549, 0.0, 0.568627451, + 0.20784313725490197, 0.431372549, 0.0, 0.568627451, 0.21176470588235294, 0.431372549, 0.0, + 0.568627451, 0.21568627450980393, 0.431372549, 0.0, 0.568627451, 0.2196078431372549, + 0.431372549, 0.0, 0.568627451, 0.2235294117647059, 0.431372549, 0.0, 0.568627451, + 0.22745098039215686, 0.431372549, 0.0, 0.568627451, 0.23137254901960785, 0.431372549, 0.0, + 0.568627451, 0.23529411764705885, 0.431372549, 0.0, 0.568627451, 0.23921568627450984, + 0.431372549, 0.0, 0.568627451, 0.24313725490196078, 0.431372549, 0.0, 0.568627451, + 0.24705882352941178, 0.431372549, 0.0, 0.568627451, 0.25098039215686274, 0.431372549, 0.0, + 0.568627451, 0.2549019607843137, 0.431372549, 0.0, 0.568627451, 0.25882352941176473, + 0.431372549, 0.0, 0.568627451, 0.2627450980392157, 0.431372549, 0.0, 0.568627451, + 0.26666666666666666, 0.431372549, 0.0, 0.568627451, 0.27058823529411763, 0.431372549, 0.0, + 0.568627451, 0.27450980392156865, 0.431372549, 0.0, 0.568627451, 0.2784313725490196, + 0.431372549, 0.0, 0.568627451, 0.2823529411764706, 0.431372549, 0.0, 0.568627451, + 0.28627450980392155, 0.431372549, 0.0, 0.568627451, 0.2901960784313726, 0.431372549, 0.0, + 0.568627451, 0.29411764705882354, 0.431372549, 0.0, 0.568627451, 0.2980392156862745, + 0.431372549, 0.0, 0.568627451, 0.30196078431372547, 0.431372549, 0.0, 0.568627451, + 0.3058823529411765, 0.2509803922, 0.3333333333, 0.6509803922, 0.30980392156862746, + 0.2509803922, 0.3333333333, 0.6509803922, 0.3137254901960784, 0.2509803922, 0.3333333333, + 0.6509803922, 0.3176470588235294, 0.2509803922, 0.3333333333, 0.6509803922, + 0.3215686274509804, 0.2509803922, 0.3333333333, 0.6509803922, 0.3254901960784314, + 0.2509803922, 0.3333333333, 0.6509803922, 0.32941176470588235, 0.2509803922, 0.3333333333, + 0.6509803922, 0.3333333333333333, 0.2509803922, 0.3333333333, 0.6509803922, + 0.33725490196078434, 0.2509803922, 0.3333333333, 0.6509803922, 0.3411764705882353, + 0.2509803922, 0.3333333333, 0.6509803922, 0.34509803921568627, 0.2509803922, 0.3333333333, + 0.6509803922, 0.34901960784313724, 0.2509803922, 0.3333333333, 0.6509803922, + 0.35294117647058826, 0.2509803922, 0.3333333333, 0.6509803922, 0.3568627450980392, + 0.2509803922, 0.3333333333, 0.6509803922, 0.3607843137254902, 0.2509803922, 0.3333333333, + 0.6509803922, 0.36470588235294116, 0.2509803922, 0.3333333333, 0.6509803922, + 0.3686274509803922, 0.2509803922, 0.3333333333, 0.6509803922, 0.37254901960784315, + 0.2509803922, 0.3333333333, 0.6509803922, 0.3764705882352941, 0.2509803922, 0.3333333333, + 0.6509803922, 0.3803921568627451, 0.2509803922, 0.3333333333, 0.6509803922, + 0.3843137254901961, 0.2509803922, 0.3333333333, 0.6509803922, 0.38823529411764707, + 0.2509803922, 0.3333333333, 0.6509803922, 0.39215686274509803, 0.2509803922, 0.3333333333, + 0.6509803922, 0.396078431372549, 0.2509803922, 0.3333333333, 0.6509803922, 0.4, 0.2509803922, + 0.3333333333, 0.6509803922, 0.403921568627451, 0.2509803922, 0.3333333333, 0.6509803922, + 0.40784313725490196, 0.0, 0.8, 1.0, 0.4117647058823529, 0.0, 0.8, 1.0, 0.41568627450980394, + 0.0, 0.8, 1.0, 0.4196078431372549, 0.0, 0.8, 1.0, 0.4235294117647059, 0.0, 0.8, 1.0, + 0.42745098039215684, 0.0, 0.8, 1.0, 0.43137254901960786, 0.0, 0.8, 1.0, 0.43529411764705883, + 0.0, 0.8, 1.0, 0.4392156862745098, 0.0, 0.8, 1.0, 0.44313725490196076, 0.0, 0.8, 1.0, + 0.4470588235294118, 0.0, 0.8, 1.0, 0.45098039215686275, 0.0, 0.8, 1.0, 0.4549019607843137, + 0.0, 0.8, 1.0, 0.4588235294117647, 0.0, 0.8, 1.0, 0.4627450980392157, 0.0, 0.8, 1.0, + 0.4666666666666667, 0.0, 0.8, 1.0, 0.4705882352941177, 0.0, 0.8, 1.0, 0.4745098039215686, 0.0, + 0.8, 1.0, 0.4784313725490197, 0.0, 0.8, 1.0, 0.48235294117647065, 0.0, 0.8, 1.0, + 0.48627450980392156, 0.0, 0.8, 1.0, 0.49019607843137253, 0.0, 0.8, 1.0, 0.49411764705882355, + 0.0, 0.8, 1.0, 0.4980392156862745, 0.0, 0.8, 1.0, 0.5019607843137255, 0.0, 0.8, 1.0, + 0.5058823529411764, 0.0, 0.6666666667, 0.5333333333, 0.5098039215686274, 0.0, 0.6666666667, + 0.5333333333, 0.5137254901960784, 0.0, 0.6666666667, 0.5333333333, 0.5176470588235295, 0.0, + 0.6666666667, 0.5333333333, 0.5215686274509804, 0.0, 0.6666666667, 0.5333333333, + 0.5254901960784314, 0.0, 0.6666666667, 0.5333333333, 0.5294117647058824, 0.0, 0.6666666667, + 0.5333333333, 0.5333333333333333, 0.0, 0.6666666667, 0.5333333333, 0.5372549019607843, 0.0, + 0.6666666667, 0.5333333333, 0.5411764705882353, 0.0, 0.6666666667, 0.5333333333, + 0.5450980392156862, 0.0, 0.6666666667, 0.5333333333, 0.5490196078431373, 0.0, 0.6666666667, + 0.5333333333, 0.5529411764705883, 0.0, 0.6666666667, 0.5333333333, 0.5568627450980392, 0.0, + 0.6666666667, 0.5333333333, 0.5607843137254902, 0.0, 0.6666666667, 0.5333333333, + 0.5647058823529412, 0.0, 0.6666666667, 0.5333333333, 0.5686274509803921, 0.0, 0.6666666667, + 0.5333333333, 0.5725490196078431, 0.0, 0.6666666667, 0.5333333333, 0.5764705882352941, 0.0, + 0.6666666667, 0.5333333333, 0.5803921568627451, 0.0, 0.6666666667, 0.5333333333, + 0.5843137254901961, 0.0, 0.6666666667, 0.5333333333, 0.5882352941176471, 0.0, 0.6666666667, + 0.5333333333, 0.592156862745098, 0.0, 0.6666666667, 0.5333333333, 0.596078431372549, 0.0, + 0.6666666667, 0.5333333333, 0.6, 0.0, 0.6666666667, 0.5333333333, 0.6039215686274509, 0.0, + 0.6666666667, 0.5333333333, 0.6078431372549019, 0.4, 1.0, 0.4, 0.611764705882353, 0.4, 1.0, + 0.4, 0.615686274509804, 0.4, 1.0, 0.4, 0.6196078431372549, 0.4, 1.0, 0.4, 0.6235294117647059, + 0.4, 1.0, 0.4, 0.6274509803921569, 0.4, 1.0, 0.4, 0.6313725490196078, 0.4, 1.0, 0.4, + 0.6352941176470588, 0.4, 1.0, 0.4, 0.6392156862745098, 0.4, 1.0, 0.4, 0.6431372549019608, 0.4, + 1.0, 0.4, 0.6470588235294118, 0.4, 1.0, 0.4, 0.6509803921568628, 0.4, 1.0, 0.4, + 0.6549019607843137, 0.4, 1.0, 0.4, 0.6588235294117647, 0.4, 1.0, 0.4, 0.6627450980392157, 0.4, + 1.0, 0.4, 0.6666666666666666, 0.4, 1.0, 0.4, 0.6705882352941176, 0.4, 1.0, 0.4, + 0.6745098039215687, 0.4, 1.0, 0.4, 0.6784313725490196, 0.4, 1.0, 0.4, 0.6823529411764706, 0.4, + 1.0, 0.4, 0.6862745098039216, 0.4, 1.0, 0.4, 0.6901960784313725, 0.4, 1.0, 0.4, + 0.6941176470588235, 0.4, 1.0, 0.4, 0.6980392156862745, 0.4, 1.0, 0.4, 0.7019607843137254, 0.4, + 1.0, 0.4, 0.7058823529411765, 1.0, 0.9490196078, 0.0, 0.7098039215686275, 1.0, 0.9490196078, + 0.0, 0.7137254901960784, 1.0, 0.9490196078, 0.0, 0.7176470588235294, 1.0, 0.9490196078, 0.0, + 0.7215686274509804, 1.0, 0.9490196078, 0.0, 0.7254901960784313, 1.0, 0.9490196078, 0.0, + 0.7294117647058823, 1.0, 0.9490196078, 0.0, 0.7333333333333333, 1.0, 0.9490196078, 0.0, + 0.7372549019607844, 1.0, 0.9490196078, 0.0, 0.7411764705882353, 1.0, 0.9490196078, 0.0, + 0.7450980392156863, 1.0, 0.9490196078, 0.0, 0.7490196078431373, 1.0, 0.9490196078, 0.0, + 0.7529411764705882, 1.0, 0.9490196078, 0.0, 0.7568627450980392, 1.0, 0.9490196078, 0.0, + 0.7607843137254902, 1.0, 0.9490196078, 0.0, 0.7647058823529411, 1.0, 0.9490196078, 0.0, + 0.7686274509803922, 1.0, 0.9490196078, 0.0, 0.7725490196078432, 1.0, 0.9490196078, 0.0, + 0.7764705882352941, 1.0, 0.9490196078, 0.0, 0.7803921568627451, 1.0, 0.9490196078, 0.0, + 0.7843137254901961, 1.0, 0.9490196078, 0.0, 0.788235294117647, 1.0, 0.9490196078, 0.0, + 0.792156862745098, 1.0, 0.9490196078, 0.0, 0.796078431372549, 1.0, 0.9490196078, 0.0, 0.8, + 1.0, 0.9490196078, 0.0, 0.803921568627451, 1.0, 0.9490196078, 0.0, 0.807843137254902, + 0.9490196078, 0.6509803922, 0.2509803922, 0.8117647058823529, 0.9490196078, 0.6509803922, + 0.2509803922, 0.8156862745098039, 0.9490196078, 0.6509803922, 0.2509803922, + 0.8196078431372549, 0.9490196078, 0.6509803922, 0.2509803922, 0.8235294117647058, + 0.9490196078, 0.6509803922, 0.2509803922, 0.8274509803921568, 0.9490196078, 0.6509803922, + 0.2509803922, 0.8313725490196079, 0.9490196078, 0.6509803922, 0.2509803922, + 0.8352941176470589, 0.9490196078, 0.6509803922, 0.2509803922, 0.8392156862745098, + 0.9490196078, 0.6509803922, 0.2509803922, 0.8431372549019608, 0.9490196078, 0.6509803922, + 0.2509803922, 0.8470588235294118, 0.9490196078, 0.6509803922, 0.2509803922, + 0.8509803921568627, 0.9490196078, 0.6509803922, 0.2509803922, 0.8549019607843137, + 0.9490196078, 0.6509803922, 0.2509803922, 0.8588235294117647, 0.9490196078, 0.6509803922, + 0.2509803922, 0.8627450980392157, 0.9490196078, 0.6509803922, 0.2509803922, + 0.8666666666666667, 0.9490196078, 0.6509803922, 0.2509803922, 0.8705882352941177, + 0.9490196078, 0.6509803922, 0.2509803922, 0.8745098039215686, 0.9490196078, 0.6509803922, + 0.2509803922, 0.8784313725490196, 0.9490196078, 0.6509803922, 0.2509803922, + 0.8823529411764706, 0.9490196078, 0.6509803922, 0.2509803922, 0.8862745098039215, + 0.9490196078, 0.6509803922, 0.2509803922, 0.8901960784313725, 0.9490196078, 0.6509803922, + 0.2509803922, 0.8941176470588236, 0.9490196078, 0.6509803922, 0.2509803922, + 0.8980392156862745, 0.9490196078, 0.6509803922, 0.2509803922, 0.9019607843137255, + 0.9490196078, 0.6509803922, 0.2509803922, 0.9058823529411765, 0.9490196078, 0.6509803922, + 0.2509803922, 0.9098039215686274, 1.0, 0.0, 0.0, 0.9137254901960784, 1.0, 0.0, 0.0, + 0.9176470588235294, 1.0, 0.0, 0.0, 0.9215686274509803, 1.0, 0.0, 0.0, 0.9254901960784314, 1.0, + 0.0, 0.0, 0.9294117647058824, 1.0, 0.0, 0.0, 0.9333333333333333, 1.0, 0.0, 0.0, + 0.9372549019607843, 1.0, 0.0, 0.0, 0.9411764705882354, 1.0, 0.0, 0.0, 0.9450980392156864, 1.0, + 0.0, 0.0, 0.9490196078431372, 1.0, 0.0, 0.0, 0.9529411764705882, 1.0, 0.0, 0.0, + 0.9568627450980394, 1.0, 0.0, 0.0, 0.9607843137254903, 1.0, 0.0, 0.0, 0.9647058823529413, 1.0, + 0.0, 0.0, 0.9686274509803922, 1.0, 0.0, 0.0, 0.9725490196078431, 1.0, 0.0, 0.0, + 0.9764705882352941, 1.0, 0.0, 0.0, 0.9803921568627451, 1.0, 0.0, 0.0, 0.984313725490196, 1.0, + 0.0, 0.0, 0.9882352941176471, 1.0, 0.0, 0.0, 0.9921568627450981, 1.0, 0.0, 0.0, + 0.996078431372549, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, + ], + description: 'SUV', + }, + { + ColorSpace: 'RGB', + Name: 'ge_256', + name: 'ge_256', + RGBPoints: [ + 0.0, 0.0039215686, 0.0078431373, 0.0078431373, 0.00392156862745098, 0.0039215686, + 0.0078431373, 0.0078431373, 0.00784313725490196, 0.0039215686, 0.0078431373, 0.0117647059, + 0.011764705882352941, 0.0039215686, 0.0117647059, 0.0156862745, 0.01568627450980392, + 0.0039215686, 0.0117647059, 0.0196078431, 0.0196078431372549, 0.0039215686, 0.0156862745, + 0.0235294118, 0.023529411764705882, 0.0039215686, 0.0156862745, 0.0274509804, + 0.027450980392156862, 0.0039215686, 0.0196078431, 0.031372549, 0.03137254901960784, + 0.0039215686, 0.0196078431, 0.0352941176, 0.03529411764705882, 0.0039215686, 0.0235294118, + 0.0392156863, 0.0392156862745098, 0.0039215686, 0.0235294118, 0.0431372549, + 0.043137254901960784, 0.0039215686, 0.0274509804, 0.0470588235, 0.047058823529411764, + 0.0039215686, 0.0274509804, 0.0509803922, 0.050980392156862744, 0.0039215686, 0.031372549, + 0.0549019608, 0.054901960784313725, 0.0039215686, 0.031372549, 0.0588235294, + 0.05882352941176471, 0.0039215686, 0.0352941176, 0.062745098, 0.06274509803921569, + 0.0039215686, 0.0352941176, 0.0666666667, 0.06666666666666667, 0.0039215686, 0.0392156863, + 0.0705882353, 0.07058823529411765, 0.0039215686, 0.0392156863, 0.0745098039, + 0.07450980392156863, 0.0039215686, 0.0431372549, 0.0784313725, 0.0784313725490196, + 0.0039215686, 0.0431372549, 0.0823529412, 0.08235294117647059, 0.0039215686, 0.0470588235, + 0.0862745098, 0.08627450980392157, 0.0039215686, 0.0470588235, 0.0901960784, + 0.09019607843137255, 0.0039215686, 0.0509803922, 0.0941176471, 0.09411764705882353, + 0.0039215686, 0.0509803922, 0.0980392157, 0.09803921568627451, 0.0039215686, 0.0549019608, + 0.1019607843, 0.10196078431372549, 0.0039215686, 0.0549019608, 0.1058823529, + 0.10588235294117647, 0.0039215686, 0.0588235294, 0.1098039216, 0.10980392156862745, + 0.0039215686, 0.0588235294, 0.1137254902, 0.11372549019607843, 0.0039215686, 0.062745098, + 0.1176470588, 0.11764705882352942, 0.0039215686, 0.062745098, 0.1215686275, + 0.12156862745098039, 0.0039215686, 0.0666666667, 0.1254901961, 0.12549019607843137, + 0.0039215686, 0.0666666667, 0.1294117647, 0.12941176470588237, 0.0039215686, 0.0705882353, + 0.1333333333, 0.13333333333333333, 0.0039215686, 0.0705882353, 0.137254902, + 0.13725490196078433, 0.0039215686, 0.0745098039, 0.1411764706, 0.1411764705882353, + 0.0039215686, 0.0745098039, 0.1450980392, 0.1450980392156863, 0.0039215686, 0.0784313725, + 0.1490196078, 0.14901960784313725, 0.0039215686, 0.0784313725, 0.1529411765, + 0.15294117647058825, 0.0039215686, 0.0823529412, 0.1568627451, 0.1568627450980392, + 0.0039215686, 0.0823529412, 0.1607843137, 0.1607843137254902, 0.0039215686, 0.0862745098, + 0.1647058824, 0.16470588235294117, 0.0039215686, 0.0862745098, 0.168627451, + 0.16862745098039217, 0.0039215686, 0.0901960784, 0.1725490196, 0.17254901960784313, + 0.0039215686, 0.0901960784, 0.1764705882, 0.17647058823529413, 0.0039215686, 0.0941176471, + 0.1803921569, 0.1803921568627451, 0.0039215686, 0.0941176471, 0.1843137255, + 0.1843137254901961, 0.0039215686, 0.0980392157, 0.1882352941, 0.18823529411764706, + 0.0039215686, 0.0980392157, 0.1921568627, 0.19215686274509805, 0.0039215686, 0.1019607843, + 0.1960784314, 0.19607843137254902, 0.0039215686, 0.1019607843, 0.2, 0.2, 0.0039215686, + 0.1058823529, 0.2039215686, 0.20392156862745098, 0.0039215686, 0.1058823529, 0.2078431373, + 0.20784313725490197, 0.0039215686, 0.1098039216, 0.2117647059, 0.21176470588235294, + 0.0039215686, 0.1098039216, 0.2156862745, 0.21568627450980393, 0.0039215686, 0.1137254902, + 0.2196078431, 0.2196078431372549, 0.0039215686, 0.1137254902, 0.2235294118, + 0.2235294117647059, 0.0039215686, 0.1176470588, 0.2274509804, 0.22745098039215686, + 0.0039215686, 0.1176470588, 0.231372549, 0.23137254901960785, 0.0039215686, 0.1215686275, + 0.2352941176, 0.23529411764705885, 0.0039215686, 0.1215686275, 0.2392156863, + 0.23921568627450984, 0.0039215686, 0.1254901961, 0.2431372549, 0.24313725490196078, + 0.0039215686, 0.1254901961, 0.2470588235, 0.24705882352941178, 0.0039215686, 0.1294117647, + 0.2509803922, 0.25098039215686274, 0.0039215686, 0.1294117647, 0.2509803922, + 0.2549019607843137, 0.0078431373, 0.1254901961, 0.2549019608, 0.25882352941176473, + 0.0156862745, 0.1254901961, 0.2588235294, 0.2627450980392157, 0.0235294118, 0.1215686275, + 0.262745098, 0.26666666666666666, 0.031372549, 0.1215686275, 0.2666666667, + 0.27058823529411763, 0.0392156863, 0.1176470588, 0.2705882353, 0.27450980392156865, + 0.0470588235, 0.1176470588, 0.2745098039, 0.2784313725490196, 0.0549019608, 0.1137254902, + 0.2784313725, 0.2823529411764706, 0.062745098, 0.1137254902, 0.2823529412, + 0.28627450980392155, 0.0705882353, 0.1098039216, 0.2862745098, 0.2901960784313726, + 0.0784313725, 0.1098039216, 0.2901960784, 0.29411764705882354, 0.0862745098, 0.1058823529, + 0.2941176471, 0.2980392156862745, 0.0941176471, 0.1058823529, 0.2980392157, + 0.30196078431372547, 0.1019607843, 0.1019607843, 0.3019607843, 0.3058823529411765, + 0.1098039216, 0.1019607843, 0.3058823529, 0.30980392156862746, 0.1176470588, 0.0980392157, + 0.3098039216, 0.3137254901960784, 0.1254901961, 0.0980392157, 0.3137254902, + 0.3176470588235294, 0.1333333333, 0.0941176471, 0.3176470588, 0.3215686274509804, + 0.1411764706, 0.0941176471, 0.3215686275, 0.3254901960784314, 0.1490196078, 0.0901960784, + 0.3254901961, 0.32941176470588235, 0.1568627451, 0.0901960784, 0.3294117647, + 0.3333333333333333, 0.1647058824, 0.0862745098, 0.3333333333, 0.33725490196078434, + 0.1725490196, 0.0862745098, 0.337254902, 0.3411764705882353, 0.1803921569, 0.0823529412, + 0.3411764706, 0.34509803921568627, 0.1882352941, 0.0823529412, 0.3450980392, + 0.34901960784313724, 0.1960784314, 0.0784313725, 0.3490196078, 0.35294117647058826, + 0.2039215686, 0.0784313725, 0.3529411765, 0.3568627450980392, 0.2117647059, 0.0745098039, + 0.3568627451, 0.3607843137254902, 0.2196078431, 0.0745098039, 0.3607843137, + 0.36470588235294116, 0.2274509804, 0.0705882353, 0.3647058824, 0.3686274509803922, + 0.2352941176, 0.0705882353, 0.368627451, 0.37254901960784315, 0.2431372549, 0.0666666667, + 0.3725490196, 0.3764705882352941, 0.2509803922, 0.0666666667, 0.3764705882, + 0.3803921568627451, 0.2549019608, 0.062745098, 0.3803921569, 0.3843137254901961, 0.262745098, + 0.062745098, 0.3843137255, 0.38823529411764707, 0.2705882353, 0.0588235294, 0.3882352941, + 0.39215686274509803, 0.2784313725, 0.0588235294, 0.3921568627, 0.396078431372549, + 0.2862745098, 0.0549019608, 0.3960784314, 0.4, 0.2941176471, 0.0549019608, 0.4, + 0.403921568627451, 0.3019607843, 0.0509803922, 0.4039215686, 0.40784313725490196, + 0.3098039216, 0.0509803922, 0.4078431373, 0.4117647058823529, 0.3176470588, 0.0470588235, + 0.4117647059, 0.41568627450980394, 0.3254901961, 0.0470588235, 0.4156862745, + 0.4196078431372549, 0.3333333333, 0.0431372549, 0.4196078431, 0.4235294117647059, + 0.3411764706, 0.0431372549, 0.4235294118, 0.42745098039215684, 0.3490196078, 0.0392156863, + 0.4274509804, 0.43137254901960786, 0.3568627451, 0.0392156863, 0.431372549, + 0.43529411764705883, 0.3647058824, 0.0352941176, 0.4352941176, 0.4392156862745098, + 0.3725490196, 0.0352941176, 0.4392156863, 0.44313725490196076, 0.3803921569, 0.031372549, + 0.4431372549, 0.4470588235294118, 0.3882352941, 0.031372549, 0.4470588235, + 0.45098039215686275, 0.3960784314, 0.0274509804, 0.4509803922, 0.4549019607843137, + 0.4039215686, 0.0274509804, 0.4549019608, 0.4588235294117647, 0.4117647059, 0.0235294118, + 0.4588235294, 0.4627450980392157, 0.4196078431, 0.0235294118, 0.462745098, 0.4666666666666667, + 0.4274509804, 0.0196078431, 0.4666666667, 0.4705882352941177, 0.4352941176, 0.0196078431, + 0.4705882353, 0.4745098039215686, 0.4431372549, 0.0156862745, 0.4745098039, + 0.4784313725490197, 0.4509803922, 0.0156862745, 0.4784313725, 0.48235294117647065, + 0.4588235294, 0.0117647059, 0.4823529412, 0.48627450980392156, 0.4666666667, 0.0117647059, + 0.4862745098, 0.49019607843137253, 0.4745098039, 0.0078431373, 0.4901960784, + 0.49411764705882355, 0.4823529412, 0.0078431373, 0.4941176471, 0.4980392156862745, + 0.4901960784, 0.0039215686, 0.4980392157, 0.5019607843137255, 0.4980392157, 0.0117647059, + 0.4980392157, 0.5058823529411764, 0.5058823529, 0.0156862745, 0.4901960784, + 0.5098039215686274, 0.5137254902, 0.0235294118, 0.4823529412, 0.5137254901960784, + 0.5215686275, 0.0274509804, 0.4745098039, 0.5176470588235295, 0.5294117647, 0.0352941176, + 0.4666666667, 0.5215686274509804, 0.537254902, 0.0392156863, 0.4588235294, 0.5254901960784314, + 0.5450980392, 0.0470588235, 0.4509803922, 0.5294117647058824, 0.5529411765, 0.0509803922, + 0.4431372549, 0.5333333333333333, 0.5607843137, 0.0588235294, 0.4352941176, + 0.5372549019607843, 0.568627451, 0.062745098, 0.4274509804, 0.5411764705882353, 0.5764705882, + 0.0705882353, 0.4196078431, 0.5450980392156862, 0.5843137255, 0.0745098039, 0.4117647059, + 0.5490196078431373, 0.5921568627, 0.0823529412, 0.4039215686, 0.5529411764705883, 0.6, + 0.0862745098, 0.3960784314, 0.5568627450980392, 0.6078431373, 0.0941176471, 0.3882352941, + 0.5607843137254902, 0.6156862745, 0.0980392157, 0.3803921569, 0.5647058823529412, + 0.6235294118, 0.1058823529, 0.3725490196, 0.5686274509803921, 0.631372549, 0.1098039216, + 0.3647058824, 0.5725490196078431, 0.6392156863, 0.1176470588, 0.3568627451, + 0.5764705882352941, 0.6470588235, 0.1215686275, 0.3490196078, 0.5803921568627451, + 0.6549019608, 0.1294117647, 0.3411764706, 0.5843137254901961, 0.662745098, 0.1333333333, + 0.3333333333, 0.5882352941176471, 0.6705882353, 0.1411764706, 0.3254901961, 0.592156862745098, + 0.6784313725, 0.1450980392, 0.3176470588, 0.596078431372549, 0.6862745098, 0.1529411765, + 0.3098039216, 0.6, 0.6941176471, 0.1568627451, 0.3019607843, 0.6039215686274509, 0.7019607843, + 0.1647058824, 0.2941176471, 0.6078431372549019, 0.7098039216, 0.168627451, 0.2862745098, + 0.611764705882353, 0.7176470588, 0.1764705882, 0.2784313725, 0.615686274509804, 0.7254901961, + 0.1803921569, 0.2705882353, 0.6196078431372549, 0.7333333333, 0.1882352941, 0.262745098, + 0.6235294117647059, 0.7411764706, 0.1921568627, 0.2549019608, 0.6274509803921569, + 0.7490196078, 0.2, 0.2509803922, 0.6313725490196078, 0.7529411765, 0.2039215686, 0.2431372549, + 0.6352941176470588, 0.7607843137, 0.2117647059, 0.2352941176, 0.6392156862745098, 0.768627451, + 0.2156862745, 0.2274509804, 0.6431372549019608, 0.7764705882, 0.2235294118, 0.2196078431, + 0.6470588235294118, 0.7843137255, 0.2274509804, 0.2117647059, 0.6509803921568628, + 0.7921568627, 0.2352941176, 0.2039215686, 0.6549019607843137, 0.8, 0.2392156863, 0.1960784314, + 0.6588235294117647, 0.8078431373, 0.2470588235, 0.1882352941, 0.6627450980392157, + 0.8156862745, 0.2509803922, 0.1803921569, 0.6666666666666666, 0.8235294118, 0.2549019608, + 0.1725490196, 0.6705882352941176, 0.831372549, 0.2588235294, 0.1647058824, 0.6745098039215687, + 0.8392156863, 0.2666666667, 0.1568627451, 0.6784313725490196, 0.8470588235, 0.2705882353, + 0.1490196078, 0.6823529411764706, 0.8549019608, 0.2784313725, 0.1411764706, + 0.6862745098039216, 0.862745098, 0.2823529412, 0.1333333333, 0.6901960784313725, 0.8705882353, + 0.2901960784, 0.1254901961, 0.6941176470588235, 0.8784313725, 0.2941176471, 0.1176470588, + 0.6980392156862745, 0.8862745098, 0.3019607843, 0.1098039216, 0.7019607843137254, + 0.8941176471, 0.3058823529, 0.1019607843, 0.7058823529411765, 0.9019607843, 0.3137254902, + 0.0941176471, 0.7098039215686275, 0.9098039216, 0.3176470588, 0.0862745098, + 0.7137254901960784, 0.9176470588, 0.3254901961, 0.0784313725, 0.7176470588235294, + 0.9254901961, 0.3294117647, 0.0705882353, 0.7215686274509804, 0.9333333333, 0.337254902, + 0.062745098, 0.7254901960784313, 0.9411764706, 0.3411764706, 0.0549019608, 0.7294117647058823, + 0.9490196078, 0.3490196078, 0.0470588235, 0.7333333333333333, 0.9568627451, 0.3529411765, + 0.0392156863, 0.7372549019607844, 0.9647058824, 0.3607843137, 0.031372549, 0.7411764705882353, + 0.9725490196, 0.3647058824, 0.0235294118, 0.7450980392156863, 0.9803921569, 0.3725490196, + 0.0156862745, 0.7490196078431373, 0.9882352941, 0.3725490196, 0.0039215686, + 0.7529411764705882, 0.9960784314, 0.3843137255, 0.0156862745, 0.7568627450980392, + 0.9960784314, 0.3921568627, 0.031372549, 0.7607843137254902, 0.9960784314, 0.4039215686, + 0.0470588235, 0.7647058823529411, 0.9960784314, 0.4117647059, 0.062745098, 0.7686274509803922, + 0.9960784314, 0.4235294118, 0.0784313725, 0.7725490196078432, 0.9960784314, 0.431372549, + 0.0941176471, 0.7764705882352941, 0.9960784314, 0.4431372549, 0.1098039216, + 0.7803921568627451, 0.9960784314, 0.4509803922, 0.1254901961, 0.7843137254901961, + 0.9960784314, 0.462745098, 0.1411764706, 0.788235294117647, 0.9960784314, 0.4705882353, + 0.1568627451, 0.792156862745098, 0.9960784314, 0.4823529412, 0.1725490196, 0.796078431372549, + 0.9960784314, 0.4901960784, 0.1882352941, 0.8, 0.9960784314, 0.5019607843, 0.2039215686, + 0.803921568627451, 0.9960784314, 0.5098039216, 0.2196078431, 0.807843137254902, 0.9960784314, + 0.5215686275, 0.2352941176, 0.8117647058823529, 0.9960784314, 0.5294117647, 0.2509803922, + 0.8156862745098039, 0.9960784314, 0.5411764706, 0.262745098, 0.8196078431372549, 0.9960784314, + 0.5490196078, 0.2784313725, 0.8235294117647058, 0.9960784314, 0.5607843137, 0.2941176471, + 0.8274509803921568, 0.9960784314, 0.568627451, 0.3098039216, 0.8313725490196079, 0.9960784314, + 0.5803921569, 0.3254901961, 0.8352941176470589, 0.9960784314, 0.5882352941, 0.3411764706, + 0.8392156862745098, 0.9960784314, 0.6, 0.3568627451, 0.8431372549019608, 0.9960784314, + 0.6078431373, 0.3725490196, 0.8470588235294118, 0.9960784314, 0.6196078431, 0.3882352941, + 0.8509803921568627, 0.9960784314, 0.6274509804, 0.4039215686, 0.8549019607843137, + 0.9960784314, 0.6392156863, 0.4196078431, 0.8588235294117647, 0.9960784314, 0.6470588235, + 0.4352941176, 0.8627450980392157, 0.9960784314, 0.6588235294, 0.4509803922, + 0.8666666666666667, 0.9960784314, 0.6666666667, 0.4666666667, 0.8705882352941177, + 0.9960784314, 0.6784313725, 0.4823529412, 0.8745098039215686, 0.9960784314, 0.6862745098, + 0.4980392157, 0.8784313725490196, 0.9960784314, 0.6980392157, 0.5137254902, + 0.8823529411764706, 0.9960784314, 0.7058823529, 0.5294117647, 0.8862745098039215, + 0.9960784314, 0.7176470588, 0.5450980392, 0.8901960784313725, 0.9960784314, 0.7254901961, + 0.5607843137, 0.8941176470588236, 0.9960784314, 0.737254902, 0.5764705882, 0.8980392156862745, + 0.9960784314, 0.7450980392, 0.5921568627, 0.9019607843137255, 0.9960784314, 0.7529411765, + 0.6078431373, 0.9058823529411765, 0.9960784314, 0.7607843137, 0.6235294118, + 0.9098039215686274, 0.9960784314, 0.7725490196, 0.6392156863, 0.9137254901960784, + 0.9960784314, 0.7803921569, 0.6549019608, 0.9176470588235294, 0.9960784314, 0.7921568627, + 0.6705882353, 0.9215686274509803, 0.9960784314, 0.8, 0.6862745098, 0.9254901960784314, + 0.9960784314, 0.8117647059, 0.7019607843, 0.9294117647058824, 0.9960784314, 0.8196078431, + 0.7176470588, 0.9333333333333333, 0.9960784314, 0.831372549, 0.7333333333, 0.9372549019607843, + 0.9960784314, 0.8392156863, 0.7490196078, 0.9411764705882354, 0.9960784314, 0.8509803922, + 0.7607843137, 0.9450980392156864, 0.9960784314, 0.8588235294, 0.7764705882, + 0.9490196078431372, 0.9960784314, 0.8705882353, 0.7921568627, 0.9529411764705882, + 0.9960784314, 0.8784313725, 0.8078431373, 0.9568627450980394, 0.9960784314, 0.8901960784, + 0.8235294118, 0.9607843137254903, 0.9960784314, 0.8980392157, 0.8392156863, + 0.9647058823529413, 0.9960784314, 0.9098039216, 0.8549019608, 0.9686274509803922, + 0.9960784314, 0.9176470588, 0.8705882353, 0.9725490196078431, 0.9960784314, 0.9294117647, + 0.8862745098, 0.9764705882352941, 0.9960784314, 0.937254902, 0.9019607843, 0.9803921568627451, + 0.9960784314, 0.9490196078, 0.9176470588, 0.984313725490196, 0.9960784314, 0.9568627451, + 0.9333333333, 0.9882352941176471, 0.9960784314, 0.968627451, 0.9490196078, 0.9921568627450981, + 0.9960784314, 0.9764705882, 0.9647058824, 0.996078431372549, 0.9960784314, 0.9882352941, + 0.9803921569, 1.0, 0.9960784314, 0.9882352941, 0.9803921569, + ], + description: 'GE 256', + }, + { + ColorSpace: 'RGB', + Name: 'ge', + name: 'ge', + RGBPoints: [ + 0.0, 0.0078431373, 0.0078431373, 0.0078431373, 0.00392156862745098, 0.0078431373, + 0.0078431373, 0.0078431373, 0.00784313725490196, 0.0078431373, 0.0078431373, 0.0078431373, + 0.011764705882352941, 0.0078431373, 0.0078431373, 0.0078431373, 0.01568627450980392, + 0.0078431373, 0.0078431373, 0.0078431373, 0.0196078431372549, 0.0078431373, 0.0078431373, + 0.0078431373, 0.023529411764705882, 0.0078431373, 0.0078431373, 0.0078431373, + 0.027450980392156862, 0.0078431373, 0.0078431373, 0.0078431373, 0.03137254901960784, + 0.0078431373, 0.0078431373, 0.0078431373, 0.03529411764705882, 0.0078431373, 0.0078431373, + 0.0078431373, 0.0392156862745098, 0.0078431373, 0.0078431373, 0.0078431373, + 0.043137254901960784, 0.0078431373, 0.0078431373, 0.0078431373, 0.047058823529411764, + 0.0078431373, 0.0078431373, 0.0078431373, 0.050980392156862744, 0.0078431373, 0.0078431373, + 0.0078431373, 0.054901960784313725, 0.0078431373, 0.0078431373, 0.0078431373, + 0.05882352941176471, 0.0117647059, 0.0078431373, 0.0078431373, 0.06274509803921569, + 0.0078431373, 0.0156862745, 0.0156862745, 0.06666666666666667, 0.0078431373, 0.0235294118, + 0.0235294118, 0.07058823529411765, 0.0078431373, 0.031372549, 0.031372549, + 0.07450980392156863, 0.0078431373, 0.0392156863, 0.0392156863, 0.0784313725490196, + 0.0078431373, 0.0470588235, 0.0470588235, 0.08235294117647059, 0.0078431373, 0.0549019608, + 0.0549019608, 0.08627450980392157, 0.0078431373, 0.062745098, 0.062745098, + 0.09019607843137255, 0.0078431373, 0.0705882353, 0.0705882353, 0.09411764705882353, + 0.0078431373, 0.0784313725, 0.0784313725, 0.09803921568627451, 0.0078431373, 0.0901960784, + 0.0862745098, 0.10196078431372549, 0.0078431373, 0.0980392157, 0.0941176471, + 0.10588235294117647, 0.0078431373, 0.1058823529, 0.1019607843, 0.10980392156862745, + 0.0078431373, 0.1137254902, 0.1098039216, 0.11372549019607843, 0.0078431373, 0.1215686275, + 0.1176470588, 0.11764705882352942, 0.0078431373, 0.1294117647, 0.1254901961, + 0.12156862745098039, 0.0078431373, 0.137254902, 0.1333333333, 0.12549019607843137, + 0.0078431373, 0.1450980392, 0.1411764706, 0.12941176470588237, 0.0078431373, 0.1529411765, + 0.1490196078, 0.13333333333333333, 0.0078431373, 0.1647058824, 0.1568627451, + 0.13725490196078433, 0.0078431373, 0.1725490196, 0.1647058824, 0.1411764705882353, + 0.0078431373, 0.1803921569, 0.1725490196, 0.1450980392156863, 0.0078431373, 0.1882352941, + 0.1803921569, 0.14901960784313725, 0.0078431373, 0.1960784314, 0.1882352941, + 0.15294117647058825, 0.0078431373, 0.2039215686, 0.1960784314, 0.1568627450980392, + 0.0078431373, 0.2117647059, 0.2039215686, 0.1607843137254902, 0.0078431373, 0.2196078431, + 0.2117647059, 0.16470588235294117, 0.0078431373, 0.2274509804, 0.2196078431, + 0.16862745098039217, 0.0078431373, 0.2352941176, 0.2274509804, 0.17254901960784313, + 0.0078431373, 0.2470588235, 0.2352941176, 0.17647058823529413, 0.0078431373, 0.2509803922, + 0.2431372549, 0.1803921568627451, 0.0078431373, 0.2549019608, 0.2509803922, + 0.1843137254901961, 0.0078431373, 0.262745098, 0.2509803922, 0.18823529411764706, + 0.0078431373, 0.2705882353, 0.2588235294, 0.19215686274509805, 0.0078431373, 0.2784313725, + 0.2666666667, 0.19607843137254902, 0.0078431373, 0.2862745098, 0.2745098039, 0.2, + 0.0078431373, 0.2941176471, 0.2823529412, 0.20392156862745098, 0.0078431373, 0.3019607843, + 0.2901960784, 0.20784313725490197, 0.0078431373, 0.3137254902, 0.2980392157, + 0.21176470588235294, 0.0078431373, 0.3215686275, 0.3058823529, 0.21568627450980393, + 0.0078431373, 0.3294117647, 0.3137254902, 0.2196078431372549, 0.0078431373, 0.337254902, + 0.3215686275, 0.2235294117647059, 0.0078431373, 0.3450980392, 0.3294117647, + 0.22745098039215686, 0.0078431373, 0.3529411765, 0.337254902, 0.23137254901960785, + 0.0078431373, 0.3607843137, 0.3450980392, 0.23529411764705885, 0.0078431373, 0.368627451, + 0.3529411765, 0.23921568627450984, 0.0078431373, 0.3764705882, 0.3607843137, + 0.24313725490196078, 0.0078431373, 0.3843137255, 0.368627451, 0.24705882352941178, + 0.0078431373, 0.3960784314, 0.3764705882, 0.25098039215686274, 0.0078431373, 0.4039215686, + 0.3843137255, 0.2549019607843137, 0.0078431373, 0.4117647059, 0.3921568627, + 0.25882352941176473, 0.0078431373, 0.4196078431, 0.4, 0.2627450980392157, 0.0078431373, + 0.4274509804, 0.4078431373, 0.26666666666666666, 0.0078431373, 0.4352941176, 0.4156862745, + 0.27058823529411763, 0.0078431373, 0.4431372549, 0.4235294118, 0.27450980392156865, + 0.0078431373, 0.4509803922, 0.431372549, 0.2784313725490196, 0.0078431373, 0.4588235294, + 0.4392156863, 0.2823529411764706, 0.0078431373, 0.4705882353, 0.4470588235, + 0.28627450980392155, 0.0078431373, 0.4784313725, 0.4549019608, 0.2901960784313726, + 0.0078431373, 0.4862745098, 0.462745098, 0.29411764705882354, 0.0078431373, 0.4941176471, + 0.4705882353, 0.2980392156862745, 0.0078431373, 0.5019607843, 0.4784313725, + 0.30196078431372547, 0.0117647059, 0.5098039216, 0.4862745098, 0.3058823529411765, + 0.0196078431, 0.5019607843, 0.4941176471, 0.30980392156862746, 0.0274509804, 0.4941176471, + 0.5058823529, 0.3137254901960784, 0.0352941176, 0.4862745098, 0.5137254902, + 0.3176470588235294, 0.0431372549, 0.4784313725, 0.5215686275, 0.3215686274509804, + 0.0509803922, 0.4705882353, 0.5294117647, 0.3254901960784314, 0.0588235294, 0.462745098, + 0.537254902, 0.32941176470588235, 0.0666666667, 0.4549019608, 0.5450980392, + 0.3333333333333333, 0.0745098039, 0.4470588235, 0.5529411765, 0.33725490196078434, + 0.0823529412, 0.4392156863, 0.5607843137, 0.3411764705882353, 0.0901960784, 0.431372549, + 0.568627451, 0.34509803921568627, 0.0980392157, 0.4235294118, 0.5764705882, + 0.34901960784313724, 0.1058823529, 0.4156862745, 0.5843137255, 0.35294117647058826, + 0.1137254902, 0.4078431373, 0.5921568627, 0.3568627450980392, 0.1215686275, 0.4, 0.6, + 0.3607843137254902, 0.1294117647, 0.3921568627, 0.6078431373, 0.36470588235294116, + 0.137254902, 0.3843137255, 0.6156862745, 0.3686274509803922, 0.1450980392, 0.3764705882, + 0.6235294118, 0.37254901960784315, 0.1529411765, 0.368627451, 0.631372549, 0.3764705882352941, + 0.1607843137, 0.3607843137, 0.6392156863, 0.3803921568627451, 0.168627451, 0.3529411765, + 0.6470588235, 0.3843137254901961, 0.1764705882, 0.3450980392, 0.6549019608, + 0.38823529411764707, 0.1843137255, 0.337254902, 0.662745098, 0.39215686274509803, + 0.1921568627, 0.3294117647, 0.6705882353, 0.396078431372549, 0.2, 0.3215686275, 0.6784313725, + 0.4, 0.2078431373, 0.3137254902, 0.6862745098, 0.403921568627451, 0.2156862745, 0.3058823529, + 0.6941176471, 0.40784313725490196, 0.2235294118, 0.2980392157, 0.7019607843, + 0.4117647058823529, 0.231372549, 0.2901960784, 0.7098039216, 0.41568627450980394, + 0.2392156863, 0.2823529412, 0.7176470588, 0.4196078431372549, 0.2470588235, 0.2745098039, + 0.7254901961, 0.4235294117647059, 0.2509803922, 0.2666666667, 0.7333333333, + 0.42745098039215684, 0.2509803922, 0.2588235294, 0.7411764706, 0.43137254901960786, + 0.2588235294, 0.2509803922, 0.7490196078, 0.43529411764705883, 0.2666666667, 0.2509803922, + 0.7490196078, 0.4392156862745098, 0.2745098039, 0.2431372549, 0.7568627451, + 0.44313725490196076, 0.2823529412, 0.2352941176, 0.7647058824, 0.4470588235294118, + 0.2901960784, 0.2274509804, 0.7725490196, 0.45098039215686275, 0.2980392157, 0.2196078431, + 0.7803921569, 0.4549019607843137, 0.3058823529, 0.2117647059, 0.7882352941, + 0.4588235294117647, 0.3137254902, 0.2039215686, 0.7960784314, 0.4627450980392157, + 0.3215686275, 0.1960784314, 0.8039215686, 0.4666666666666667, 0.3294117647, 0.1882352941, + 0.8117647059, 0.4705882352941177, 0.337254902, 0.1803921569, 0.8196078431, 0.4745098039215686, + 0.3450980392, 0.1725490196, 0.8274509804, 0.4784313725490197, 0.3529411765, 0.1647058824, + 0.8352941176, 0.48235294117647065, 0.3607843137, 0.1568627451, 0.8431372549, + 0.48627450980392156, 0.368627451, 0.1490196078, 0.8509803922, 0.49019607843137253, + 0.3764705882, 0.1411764706, 0.8588235294, 0.49411764705882355, 0.3843137255, 0.1333333333, + 0.8666666667, 0.4980392156862745, 0.3921568627, 0.1254901961, 0.8745098039, + 0.5019607843137255, 0.4, 0.1176470588, 0.8823529412, 0.5058823529411764, 0.4078431373, + 0.1098039216, 0.8901960784, 0.5098039215686274, 0.4156862745, 0.1019607843, 0.8980392157, + 0.5137254901960784, 0.4235294118, 0.0941176471, 0.9058823529, 0.5176470588235295, 0.431372549, + 0.0862745098, 0.9137254902, 0.5215686274509804, 0.4392156863, 0.0784313725, 0.9215686275, + 0.5254901960784314, 0.4470588235, 0.0705882353, 0.9294117647, 0.5294117647058824, + 0.4549019608, 0.062745098, 0.937254902, 0.5333333333333333, 0.462745098, 0.0549019608, + 0.9450980392, 0.5372549019607843, 0.4705882353, 0.0470588235, 0.9529411765, + 0.5411764705882353, 0.4784313725, 0.0392156863, 0.9607843137, 0.5450980392156862, + 0.4862745098, 0.031372549, 0.968627451, 0.5490196078431373, 0.4941176471, 0.0235294118, + 0.9764705882, 0.5529411764705883, 0.4980392157, 0.0156862745, 0.9843137255, + 0.5568627450980392, 0.5058823529, 0.0078431373, 0.9921568627, 0.5607843137254902, + 0.5137254902, 0.0156862745, 0.9803921569, 0.5647058823529412, 0.5215686275, 0.0235294118, + 0.9647058824, 0.5686274509803921, 0.5294117647, 0.0352941176, 0.9490196078, + 0.5725490196078431, 0.537254902, 0.0431372549, 0.9333333333, 0.5764705882352941, 0.5450980392, + 0.0509803922, 0.9176470588, 0.5803921568627451, 0.5529411765, 0.062745098, 0.9019607843, + 0.5843137254901961, 0.5607843137, 0.0705882353, 0.8862745098, 0.5882352941176471, 0.568627451, + 0.0784313725, 0.8705882353, 0.592156862745098, 0.5764705882, 0.0901960784, 0.8549019608, + 0.596078431372549, 0.5843137255, 0.0980392157, 0.8392156863, 0.6, 0.5921568627, 0.1098039216, + 0.8235294118, 0.6039215686274509, 0.6, 0.1176470588, 0.8078431373, 0.6078431372549019, + 0.6078431373, 0.1254901961, 0.7921568627, 0.611764705882353, 0.6156862745, 0.137254902, + 0.7764705882, 0.615686274509804, 0.6235294118, 0.1450980392, 0.7607843137, 0.6196078431372549, + 0.631372549, 0.1529411765, 0.7490196078, 0.6235294117647059, 0.6392156863, 0.1647058824, + 0.737254902, 0.6274509803921569, 0.6470588235, 0.1725490196, 0.7215686275, 0.6313725490196078, + 0.6549019608, 0.1843137255, 0.7058823529, 0.6352941176470588, 0.662745098, 0.1921568627, + 0.6901960784, 0.6392156862745098, 0.6705882353, 0.2, 0.6745098039, 0.6431372549019608, + 0.6784313725, 0.2117647059, 0.6588235294, 0.6470588235294118, 0.6862745098, 0.2196078431, + 0.6431372549, 0.6509803921568628, 0.6941176471, 0.2274509804, 0.6274509804, + 0.6549019607843137, 0.7019607843, 0.2392156863, 0.6117647059, 0.6588235294117647, + 0.7098039216, 0.2470588235, 0.5960784314, 0.6627450980392157, 0.7176470588, 0.2509803922, + 0.5803921569, 0.6666666666666666, 0.7254901961, 0.2588235294, 0.5647058824, + 0.6705882352941176, 0.7333333333, 0.2666666667, 0.5490196078, 0.6745098039215687, + 0.7411764706, 0.2784313725, 0.5333333333, 0.6784313725490196, 0.7490196078, 0.2862745098, + 0.5176470588, 0.6823529411764706, 0.7490196078, 0.2941176471, 0.5019607843, + 0.6862745098039216, 0.7529411765, 0.3058823529, 0.4862745098, 0.6901960784313725, + 0.7607843137, 0.3137254902, 0.4705882353, 0.6941176470588235, 0.768627451, 0.3215686275, + 0.4549019608, 0.6980392156862745, 0.7764705882, 0.3333333333, 0.4392156863, + 0.7019607843137254, 0.7843137255, 0.3411764706, 0.4235294118, 0.7058823529411765, + 0.7921568627, 0.3529411765, 0.4078431373, 0.7098039215686275, 0.8, 0.3607843137, 0.3921568627, + 0.7137254901960784, 0.8078431373, 0.368627451, 0.3764705882, 0.7176470588235294, 0.8156862745, + 0.3803921569, 0.3607843137, 0.7215686274509804, 0.8235294118, 0.3882352941, 0.3450980392, + 0.7254901960784313, 0.831372549, 0.3960784314, 0.3294117647, 0.7294117647058823, 0.8392156863, + 0.4078431373, 0.3137254902, 0.7333333333333333, 0.8470588235, 0.4156862745, 0.2980392157, + 0.7372549019607844, 0.8549019608, 0.4274509804, 0.2823529412, 0.7411764705882353, 0.862745098, + 0.4352941176, 0.2666666667, 0.7450980392156863, 0.8705882353, 0.4431372549, 0.2509803922, + 0.7490196078431373, 0.8784313725, 0.4549019608, 0.2431372549, 0.7529411764705882, + 0.8862745098, 0.462745098, 0.2274509804, 0.7568627450980392, 0.8941176471, 0.4705882353, + 0.2117647059, 0.7607843137254902, 0.9019607843, 0.4823529412, 0.1960784314, + 0.7647058823529411, 0.9098039216, 0.4901960784, 0.1803921569, 0.7686274509803922, + 0.9176470588, 0.4980392157, 0.1647058824, 0.7725490196078432, 0.9254901961, 0.5098039216, + 0.1490196078, 0.7764705882352941, 0.9333333333, 0.5176470588, 0.1333333333, + 0.7803921568627451, 0.9411764706, 0.5294117647, 0.1176470588, 0.7843137254901961, + 0.9490196078, 0.537254902, 0.1019607843, 0.788235294117647, 0.9568627451, 0.5450980392, + 0.0862745098, 0.792156862745098, 0.9647058824, 0.5568627451, 0.0705882353, 0.796078431372549, + 0.9725490196, 0.5647058824, 0.0549019608, 0.8, 0.9803921569, 0.5725490196, 0.0392156863, + 0.803921568627451, 0.9882352941, 0.5843137255, 0.0235294118, 0.807843137254902, 0.9921568627, + 0.5921568627, 0.0078431373, 0.8117647058823529, 0.9921568627, 0.6039215686, 0.0274509804, + 0.8156862745098039, 0.9921568627, 0.6117647059, 0.0509803922, 0.8196078431372549, + 0.9921568627, 0.6196078431, 0.0745098039, 0.8235294117647058, 0.9921568627, 0.631372549, + 0.0980392157, 0.8274509803921568, 0.9921568627, 0.6392156863, 0.1215686275, + 0.8313725490196079, 0.9921568627, 0.6470588235, 0.1411764706, 0.8352941176470589, + 0.9921568627, 0.6588235294, 0.1647058824, 0.8392156862745098, 0.9921568627, 0.6666666667, + 0.1882352941, 0.8431372549019608, 0.9921568627, 0.6784313725, 0.2117647059, + 0.8470588235294118, 0.9921568627, 0.6862745098, 0.2352941176, 0.8509803921568627, + 0.9921568627, 0.6941176471, 0.2509803922, 0.8549019607843137, 0.9921568627, 0.7058823529, + 0.2705882353, 0.8588235294117647, 0.9921568627, 0.7137254902, 0.2941176471, + 0.8627450980392157, 0.9921568627, 0.7215686275, 0.3176470588, 0.8666666666666667, + 0.9921568627, 0.7333333333, 0.3411764706, 0.8705882352941177, 0.9921568627, 0.7411764706, + 0.3647058824, 0.8745098039215686, 0.9921568627, 0.7490196078, 0.3843137255, + 0.8784313725490196, 0.9921568627, 0.7529411765, 0.4078431373, 0.8823529411764706, + 0.9921568627, 0.7607843137, 0.431372549, 0.8862745098039215, 0.9921568627, 0.7725490196, + 0.4549019608, 0.8901960784313725, 0.9921568627, 0.7803921569, 0.4784313725, + 0.8941176470588236, 0.9921568627, 0.7882352941, 0.4980392157, 0.8980392156862745, + 0.9921568627, 0.8, 0.5215686275, 0.9019607843137255, 0.9921568627, 0.8078431373, 0.5450980392, + 0.9058823529411765, 0.9921568627, 0.8156862745, 0.568627451, 0.9098039215686274, 0.9921568627, + 0.8274509804, 0.5921568627, 0.9137254901960784, 0.9921568627, 0.8352941176, 0.6156862745, + 0.9176470588235294, 0.9921568627, 0.8470588235, 0.6352941176, 0.9215686274509803, + 0.9921568627, 0.8549019608, 0.6588235294, 0.9254901960784314, 0.9921568627, 0.862745098, + 0.6823529412, 0.9294117647058824, 0.9921568627, 0.8745098039, 0.7058823529, + 0.9333333333333333, 0.9921568627, 0.8823529412, 0.7294117647, 0.9372549019607843, + 0.9921568627, 0.8901960784, 0.7490196078, 0.9411764705882354, 0.9921568627, 0.9019607843, + 0.7647058824, 0.9450980392156864, 0.9921568627, 0.9098039216, 0.7882352941, + 0.9490196078431372, 0.9921568627, 0.9215686275, 0.8117647059, 0.9529411764705882, + 0.9921568627, 0.9294117647, 0.8352941176, 0.9568627450980394, 0.9921568627, 0.937254902, + 0.8588235294, 0.9607843137254903, 0.9921568627, 0.9490196078, 0.8784313725, + 0.9647058823529413, 0.9921568627, 0.9568627451, 0.9019607843, 0.9686274509803922, + 0.9921568627, 0.9647058824, 0.9254901961, 0.9725490196078431, 0.9921568627, 0.9764705882, + 0.9490196078, 0.9764705882352941, 0.9921568627, 0.9843137255, 0.9725490196, + 0.9803921568627451, 0.9921568627, 0.9921568627, 0.9921568627, 0.984313725490196, 0.9921568627, + 0.9921568627, 0.9921568627, 0.9882352941176471, 0.9921568627, 0.9921568627, 0.9921568627, + 0.9921568627450981, 0.9921568627, 0.9921568627, 0.9921568627, 0.996078431372549, 0.9921568627, + 0.9921568627, 0.9921568627, 1.0, 0.9921568627, 0.9921568627, 0.9921568627, + ], + description: 'GE', + }, + { + ColorSpace: 'RGB', + Name: 'siemens', + name: 'siemens', + RGBPoints: [ + 0.0, 0.0078431373, 0.0039215686, 0.1254901961, 0.00392156862745098, 0.0078431373, + 0.0039215686, 0.1254901961, 0.00784313725490196, 0.0078431373, 0.0039215686, 0.1882352941, + 0.011764705882352941, 0.0117647059, 0.0039215686, 0.2509803922, 0.01568627450980392, + 0.0117647059, 0.0039215686, 0.3098039216, 0.0196078431372549, 0.0156862745, 0.0039215686, + 0.3725490196, 0.023529411764705882, 0.0156862745, 0.0039215686, 0.3725490196, + 0.027450980392156862, 0.0156862745, 0.0039215686, 0.3725490196, 0.03137254901960784, + 0.0156862745, 0.0039215686, 0.3725490196, 0.03529411764705882, 0.0156862745, 0.0039215686, + 0.3725490196, 0.0392156862745098, 0.0156862745, 0.0039215686, 0.3725490196, + 0.043137254901960784, 0.0156862745, 0.0039215686, 0.3725490196, 0.047058823529411764, + 0.0156862745, 0.0039215686, 0.3725490196, 0.050980392156862744, 0.0156862745, 0.0039215686, + 0.3725490196, 0.054901960784313725, 0.0156862745, 0.0039215686, 0.3725490196, + 0.05882352941176471, 0.0156862745, 0.0039215686, 0.3725490196, 0.06274509803921569, + 0.0156862745, 0.0039215686, 0.3882352941, 0.06666666666666667, 0.0156862745, 0.0039215686, + 0.4078431373, 0.07058823529411765, 0.0156862745, 0.0039215686, 0.4235294118, + 0.07450980392156863, 0.0156862745, 0.0039215686, 0.4431372549, 0.0784313725490196, + 0.0156862745, 0.0039215686, 0.462745098, 0.08235294117647059, 0.0156862745, 0.0039215686, + 0.4784313725, 0.08627450980392157, 0.0156862745, 0.0039215686, 0.4980392157, + 0.09019607843137255, 0.0196078431, 0.0039215686, 0.5137254902, 0.09411764705882353, + 0.0196078431, 0.0039215686, 0.5333333333, 0.09803921568627451, 0.0196078431, 0.0039215686, + 0.5529411765, 0.10196078431372549, 0.0196078431, 0.0039215686, 0.568627451, + 0.10588235294117647, 0.0196078431, 0.0039215686, 0.5882352941, 0.10980392156862745, + 0.0196078431, 0.0039215686, 0.6039215686, 0.11372549019607843, 0.0196078431, 0.0039215686, + 0.6235294118, 0.11764705882352942, 0.0196078431, 0.0039215686, 0.6431372549, + 0.12156862745098039, 0.0235294118, 0.0039215686, 0.6588235294, 0.12549019607843137, + 0.0235294118, 0.0039215686, 0.6784313725, 0.12941176470588237, 0.0235294118, 0.0039215686, + 0.6980392157, 0.13333333333333333, 0.0235294118, 0.0039215686, 0.7137254902, + 0.13725490196078433, 0.0235294118, 0.0039215686, 0.7333333333, 0.1411764705882353, + 0.0235294118, 0.0039215686, 0.7490196078, 0.1450980392156863, 0.0235294118, 0.0039215686, + 0.7647058824, 0.14901960784313725, 0.0235294118, 0.0039215686, 0.7843137255, + 0.15294117647058825, 0.0274509804, 0.0039215686, 0.8, 0.1568627450980392, 0.0274509804, + 0.0039215686, 0.8196078431, 0.1607843137254902, 0.0274509804, 0.0039215686, 0.8352941176, + 0.16470588235294117, 0.0274509804, 0.0039215686, 0.8549019608, 0.16862745098039217, + 0.0274509804, 0.0039215686, 0.8745098039, 0.17254901960784313, 0.0274509804, 0.0039215686, + 0.8901960784, 0.17647058823529413, 0.0274509804, 0.0039215686, 0.9098039216, + 0.1803921568627451, 0.031372549, 0.0039215686, 0.9294117647, 0.1843137254901961, 0.031372549, + 0.0039215686, 0.9254901961, 0.18823529411764706, 0.0509803922, 0.0039215686, 0.9098039216, + 0.19215686274509805, 0.0705882353, 0.0039215686, 0.8901960784, 0.19607843137254902, + 0.0901960784, 0.0039215686, 0.8705882353, 0.2, 0.1137254902, 0.0039215686, 0.8509803922, + 0.20392156862745098, 0.1333333333, 0.0039215686, 0.831372549, 0.20784313725490197, + 0.1529411765, 0.0039215686, 0.8117647059, 0.21176470588235294, 0.1725490196, 0.0039215686, + 0.7921568627, 0.21568627450980393, 0.1960784314, 0.0039215686, 0.7725490196, + 0.2196078431372549, 0.2156862745, 0.0039215686, 0.7529411765, 0.2235294117647059, + 0.2352941176, 0.0039215686, 0.737254902, 0.22745098039215686, 0.2509803922, 0.0039215686, + 0.7176470588, 0.23137254901960785, 0.2745098039, 0.0039215686, 0.6980392157, + 0.23529411764705885, 0.2941176471, 0.0039215686, 0.6784313725, 0.23921568627450984, + 0.3137254902, 0.0039215686, 0.6588235294, 0.24313725490196078, 0.3333333333, 0.0039215686, + 0.6392156863, 0.24705882352941178, 0.3568627451, 0.0039215686, 0.6196078431, + 0.25098039215686274, 0.3764705882, 0.0039215686, 0.6, 0.2549019607843137, 0.3960784314, + 0.0039215686, 0.5803921569, 0.25882352941176473, 0.4156862745, 0.0039215686, 0.5607843137, + 0.2627450980392157, 0.4392156863, 0.0039215686, 0.5411764706, 0.26666666666666666, + 0.4588235294, 0.0039215686, 0.5215686275, 0.27058823529411763, 0.4784313725, 0.0039215686, + 0.5019607843, 0.27450980392156865, 0.4980392157, 0.0039215686, 0.4823529412, + 0.2784313725490196, 0.5215686275, 0.0039215686, 0.4666666667, 0.2823529411764706, + 0.5411764706, 0.0039215686, 0.4470588235, 0.28627450980392155, 0.5607843137, 0.0039215686, + 0.4274509804, 0.2901960784313726, 0.5803921569, 0.0039215686, 0.4078431373, + 0.29411764705882354, 0.6039215686, 0.0039215686, 0.3882352941, 0.2980392156862745, + 0.6235294118, 0.0039215686, 0.368627451, 0.30196078431372547, 0.6431372549, 0.0039215686, + 0.3490196078, 0.3058823529411765, 0.662745098, 0.0039215686, 0.3294117647, + 0.30980392156862746, 0.6862745098, 0.0039215686, 0.3098039216, 0.3137254901960784, + 0.7058823529, 0.0039215686, 0.2901960784, 0.3176470588235294, 0.7254901961, 0.0039215686, + 0.2705882353, 0.3215686274509804, 0.7450980392, 0.0039215686, 0.2509803922, + 0.3254901960784314, 0.7647058824, 0.0039215686, 0.2352941176, 0.32941176470588235, + 0.7843137255, 0.0039215686, 0.2156862745, 0.3333333333333333, 0.8039215686, 0.0039215686, + 0.1960784314, 0.33725490196078434, 0.8235294118, 0.0039215686, 0.1764705882, + 0.3411764705882353, 0.8470588235, 0.0039215686, 0.1568627451, 0.34509803921568627, + 0.8666666667, 0.0039215686, 0.137254902, 0.34901960784313724, 0.8862745098, 0.0039215686, + 0.1176470588, 0.35294117647058826, 0.9058823529, 0.0039215686, 0.0980392157, + 0.3568627450980392, 0.9294117647, 0.0039215686, 0.0784313725, 0.3607843137254902, + 0.9490196078, 0.0039215686, 0.0588235294, 0.36470588235294116, 0.968627451, 0.0039215686, + 0.0392156863, 0.3686274509803922, 0.9921568627, 0.0039215686, 0.0235294118, + 0.37254901960784315, 0.9529411765, 0.0039215686, 0.0588235294, 0.3764705882352941, + 0.9529411765, 0.0078431373, 0.0549019608, 0.3803921568627451, 0.9529411765, 0.0156862745, + 0.0549019608, 0.3843137254901961, 0.9529411765, 0.0235294118, 0.0549019608, + 0.38823529411764707, 0.9529411765, 0.031372549, 0.0549019608, 0.39215686274509803, + 0.9529411765, 0.0352941176, 0.0549019608, 0.396078431372549, 0.9529411765, 0.0431372549, + 0.0549019608, 0.4, 0.9529411765, 0.0509803922, 0.0549019608, 0.403921568627451, 0.9529411765, + 0.0588235294, 0.0549019608, 0.40784313725490196, 0.9529411765, 0.062745098, 0.0549019608, + 0.4117647058823529, 0.9529411765, 0.0705882353, 0.0549019608, 0.41568627450980394, + 0.9529411765, 0.0784313725, 0.0509803922, 0.4196078431372549, 0.9529411765, 0.0862745098, + 0.0509803922, 0.4235294117647059, 0.9568627451, 0.0941176471, 0.0509803922, + 0.42745098039215684, 0.9568627451, 0.0980392157, 0.0509803922, 0.43137254901960786, + 0.9568627451, 0.1058823529, 0.0509803922, 0.43529411764705883, 0.9568627451, 0.1137254902, + 0.0509803922, 0.4392156862745098, 0.9568627451, 0.1215686275, 0.0509803922, + 0.44313725490196076, 0.9568627451, 0.1254901961, 0.0509803922, 0.4470588235294118, + 0.9568627451, 0.1333333333, 0.0509803922, 0.45098039215686275, 0.9568627451, 0.1411764706, + 0.0509803922, 0.4549019607843137, 0.9568627451, 0.1490196078, 0.0470588235, + 0.4588235294117647, 0.9568627451, 0.1568627451, 0.0470588235, 0.4627450980392157, + 0.9568627451, 0.1607843137, 0.0470588235, 0.4666666666666667, 0.9568627451, 0.168627451, + 0.0470588235, 0.4705882352941177, 0.9607843137, 0.1764705882, 0.0470588235, + 0.4745098039215686, 0.9607843137, 0.1843137255, 0.0470588235, 0.4784313725490197, + 0.9607843137, 0.1882352941, 0.0470588235, 0.48235294117647065, 0.9607843137, 0.1960784314, + 0.0470588235, 0.48627450980392156, 0.9607843137, 0.2039215686, 0.0470588235, + 0.49019607843137253, 0.9607843137, 0.2117647059, 0.0470588235, 0.49411764705882355, + 0.9607843137, 0.2196078431, 0.0431372549, 0.4980392156862745, 0.9607843137, 0.2235294118, + 0.0431372549, 0.5019607843137255, 0.9607843137, 0.231372549, 0.0431372549, 0.5058823529411764, + 0.9607843137, 0.2392156863, 0.0431372549, 0.5098039215686274, 0.9607843137, 0.2470588235, + 0.0431372549, 0.5137254901960784, 0.9607843137, 0.2509803922, 0.0431372549, + 0.5176470588235295, 0.9647058824, 0.2549019608, 0.0431372549, 0.5215686274509804, + 0.9647058824, 0.262745098, 0.0431372549, 0.5254901960784314, 0.9647058824, 0.2705882353, + 0.0431372549, 0.5294117647058824, 0.9647058824, 0.2745098039, 0.0431372549, + 0.5333333333333333, 0.9647058824, 0.2823529412, 0.0392156863, 0.5372549019607843, + 0.9647058824, 0.2901960784, 0.0392156863, 0.5411764705882353, 0.9647058824, 0.2980392157, + 0.0392156863, 0.5450980392156862, 0.9647058824, 0.3058823529, 0.0392156863, + 0.5490196078431373, 0.9647058824, 0.3098039216, 0.0392156863, 0.5529411764705883, + 0.9647058824, 0.3176470588, 0.0392156863, 0.5568627450980392, 0.9647058824, 0.3254901961, + 0.0392156863, 0.5607843137254902, 0.9647058824, 0.3333333333, 0.0392156863, + 0.5647058823529412, 0.9647058824, 0.337254902, 0.0392156863, 0.5686274509803921, 0.968627451, + 0.3450980392, 0.0392156863, 0.5725490196078431, 0.968627451, 0.3529411765, 0.0352941176, + 0.5764705882352941, 0.968627451, 0.3607843137, 0.0352941176, 0.5803921568627451, 0.968627451, + 0.368627451, 0.0352941176, 0.5843137254901961, 0.968627451, 0.3725490196, 0.0352941176, + 0.5882352941176471, 0.968627451, 0.3803921569, 0.0352941176, 0.592156862745098, 0.968627451, + 0.3882352941, 0.0352941176, 0.596078431372549, 0.968627451, 0.3960784314, 0.0352941176, 0.6, + 0.968627451, 0.4, 0.0352941176, 0.6039215686274509, 0.968627451, 0.4078431373, 0.0352941176, + 0.6078431372549019, 0.968627451, 0.4156862745, 0.0352941176, 0.611764705882353, 0.968627451, + 0.4235294118, 0.031372549, 0.615686274509804, 0.9725490196, 0.431372549, 0.031372549, + 0.6196078431372549, 0.9725490196, 0.4352941176, 0.031372549, 0.6235294117647059, 0.9725490196, + 0.4431372549, 0.031372549, 0.6274509803921569, 0.9725490196, 0.4509803922, 0.031372549, + 0.6313725490196078, 0.9725490196, 0.4588235294, 0.031372549, 0.6352941176470588, 0.9725490196, + 0.462745098, 0.031372549, 0.6392156862745098, 0.9725490196, 0.4705882353, 0.031372549, + 0.6431372549019608, 0.9725490196, 0.4784313725, 0.031372549, 0.6470588235294118, 0.9725490196, + 0.4862745098, 0.031372549, 0.6509803921568628, 0.9725490196, 0.4941176471, 0.0274509804, + 0.6549019607843137, 0.9725490196, 0.4980392157, 0.0274509804, 0.6588235294117647, + 0.9725490196, 0.5058823529, 0.0274509804, 0.6627450980392157, 0.9764705882, 0.5137254902, + 0.0274509804, 0.6666666666666666, 0.9764705882, 0.5215686275, 0.0274509804, + 0.6705882352941176, 0.9764705882, 0.5254901961, 0.0274509804, 0.6745098039215687, + 0.9764705882, 0.5333333333, 0.0274509804, 0.6784313725490196, 0.9764705882, 0.5411764706, + 0.0274509804, 0.6823529411764706, 0.9764705882, 0.5490196078, 0.0274509804, + 0.6862745098039216, 0.9764705882, 0.5529411765, 0.0274509804, 0.6901960784313725, + 0.9764705882, 0.5607843137, 0.0235294118, 0.6941176470588235, 0.9764705882, 0.568627451, + 0.0235294118, 0.6980392156862745, 0.9764705882, 0.5764705882, 0.0235294118, + 0.7019607843137254, 0.9764705882, 0.5843137255, 0.0235294118, 0.7058823529411765, + 0.9764705882, 0.5882352941, 0.0235294118, 0.7098039215686275, 0.9764705882, 0.5960784314, + 0.0235294118, 0.7137254901960784, 0.9803921569, 0.6039215686, 0.0235294118, + 0.7176470588235294, 0.9803921569, 0.6117647059, 0.0235294118, 0.7215686274509804, + 0.9803921569, 0.6156862745, 0.0235294118, 0.7254901960784313, 0.9803921569, 0.6235294118, + 0.0235294118, 0.7294117647058823, 0.9803921569, 0.631372549, 0.0196078431, 0.7333333333333333, + 0.9803921569, 0.6392156863, 0.0196078431, 0.7372549019607844, 0.9803921569, 0.6470588235, + 0.0196078431, 0.7411764705882353, 0.9803921569, 0.6509803922, 0.0196078431, + 0.7450980392156863, 0.9803921569, 0.6588235294, 0.0196078431, 0.7490196078431373, + 0.9803921569, 0.6666666667, 0.0196078431, 0.7529411764705882, 0.9803921569, 0.6745098039, + 0.0196078431, 0.7568627450980392, 0.9803921569, 0.6784313725, 0.0196078431, + 0.7607843137254902, 0.9843137255, 0.6862745098, 0.0196078431, 0.7647058823529411, + 0.9843137255, 0.6941176471, 0.0196078431, 0.7686274509803922, 0.9843137255, 0.7019607843, + 0.0156862745, 0.7725490196078432, 0.9843137255, 0.7098039216, 0.0156862745, + 0.7764705882352941, 0.9843137255, 0.7137254902, 0.0156862745, 0.7803921568627451, + 0.9843137255, 0.7215686275, 0.0156862745, 0.7843137254901961, 0.9843137255, 0.7294117647, + 0.0156862745, 0.788235294117647, 0.9843137255, 0.737254902, 0.0156862745, 0.792156862745098, + 0.9843137255, 0.7411764706, 0.0156862745, 0.796078431372549, 0.9843137255, 0.7490196078, + 0.0156862745, 0.8, 0.9843137255, 0.7529411765, 0.0156862745, 0.803921568627451, 0.9843137255, + 0.7607843137, 0.0156862745, 0.807843137254902, 0.9882352941, 0.768627451, 0.0156862745, + 0.8117647058823529, 0.9882352941, 0.768627451, 0.0156862745, 0.8156862745098039, 0.9843137255, + 0.7843137255, 0.0117647059, 0.8196078431372549, 0.9843137255, 0.8, 0.0117647059, + 0.8235294117647058, 0.9843137255, 0.8156862745, 0.0117647059, 0.8274509803921568, + 0.9803921569, 0.831372549, 0.0117647059, 0.8313725490196079, 0.9803921569, 0.8431372549, + 0.0117647059, 0.8352941176470589, 0.9803921569, 0.8588235294, 0.0078431373, + 0.8392156862745098, 0.9803921569, 0.8745098039, 0.0078431373, 0.8431372549019608, + 0.9764705882, 0.8901960784, 0.0078431373, 0.8470588235294118, 0.9764705882, 0.9058823529, + 0.0078431373, 0.8509803921568627, 0.9764705882, 0.9176470588, 0.0078431373, + 0.8549019607843137, 0.9764705882, 0.9333333333, 0.0039215686, 0.8588235294117647, + 0.9725490196, 0.9490196078, 0.0039215686, 0.8627450980392157, 0.9725490196, 0.9647058824, + 0.0039215686, 0.8666666666666667, 0.9725490196, 0.9803921569, 0.0039215686, + 0.8705882352941177, 0.9725490196, 0.9960784314, 0.0039215686, 0.8745098039215686, + 0.9725490196, 0.9960784314, 0.0039215686, 0.8784313725490196, 0.9725490196, 0.9960784314, + 0.0352941176, 0.8823529411764706, 0.9725490196, 0.9960784314, 0.0666666667, + 0.8862745098039215, 0.9725490196, 0.9960784314, 0.0980392157, 0.8901960784313725, + 0.9725490196, 0.9960784314, 0.1294117647, 0.8941176470588236, 0.9725490196, 0.9960784314, + 0.1647058824, 0.8980392156862745, 0.9764705882, 0.9960784314, 0.1960784314, + 0.9019607843137255, 0.9764705882, 0.9960784314, 0.2274509804, 0.9058823529411765, + 0.9764705882, 0.9960784314, 0.2549019608, 0.9098039215686274, 0.9764705882, 0.9960784314, + 0.2901960784, 0.9137254901960784, 0.9764705882, 0.9960784314, 0.3215686275, + 0.9176470588235294, 0.9803921569, 0.9960784314, 0.3529411765, 0.9215686274509803, + 0.9803921569, 0.9960784314, 0.3843137255, 0.9254901960784314, 0.9803921569, 0.9960784314, + 0.4156862745, 0.9294117647058824, 0.9803921569, 0.9960784314, 0.4509803922, + 0.9333333333333333, 0.9803921569, 0.9960784314, 0.4823529412, 0.9372549019607843, + 0.9843137255, 0.9960784314, 0.5137254902, 0.9411764705882354, 0.9843137255, 0.9960784314, + 0.5450980392, 0.9450980392156864, 0.9843137255, 0.9960784314, 0.5803921569, + 0.9490196078431372, 0.9843137255, 0.9960784314, 0.6117647059, 0.9529411764705882, + 0.9843137255, 0.9960784314, 0.6431372549, 0.9568627450980394, 0.9882352941, 0.9960784314, + 0.6745098039, 0.9607843137254903, 0.9882352941, 0.9960784314, 0.7058823529, + 0.9647058823529413, 0.9882352941, 0.9960784314, 0.7411764706, 0.9686274509803922, + 0.9882352941, 0.9960784314, 0.768627451, 0.9725490196078431, 0.9882352941, 0.9960784314, 0.8, + 0.9764705882352941, 0.9921568627, 0.9960784314, 0.831372549, 0.9803921568627451, 0.9921568627, + 0.9960784314, 0.8666666667, 0.984313725490196, 0.9921568627, 0.9960784314, 0.8980392157, + 0.9882352941176471, 0.9921568627, 0.9960784314, 0.9294117647, 0.9921568627450981, + 0.9921568627, 0.9960784314, 0.9607843137, 0.996078431372549, 0.9960784314, 0.9960784314, + 0.9607843137, 1.0, 0.9960784314, 0.9960784314, 0.9607843137, + ], + description: 'Siemens', + }, + { + ColorSpace: 'RGB', + Name: 'X Ray', + name: 'X Ray', + NanColor: [1, 0, 0], + RGBPoints: [0, 1, 1, 1, 1, 0, 0, 0], + description: 'X Ray', + }, + { + ColorSpace: 'RGB', + Name: 'Grayscale', + name: 'Grayscale', + NanColor: [1, 0, 0], + RGBPoints: [0, 0, 0, 0, 1, 1, 1, 1], + description: 'Grayscale', + }, +]; + +export { colormaps }; diff --git a/extensions/default/src/ViewerLayout/ViewerHeader.tsx b/extensions/default/src/ViewerLayout/ViewerHeader.tsx index c47ce1ec6..71897a5fb 100644 --- a/extensions/default/src/ViewerLayout/ViewerHeader.tsx +++ b/extensions/default/src/ViewerLayout/ViewerHeader.tsx @@ -105,6 +105,8 @@ function ViewerHeader({ hotkeysManager, extensionManager, servicesManager }) { isReturnEnabled={!!appConfig.showStudyList} onClickReturnButton={onClickReturnButton} WhiteLabeling={appConfig.whiteLabeling} + showPatientInfo={appConfig.showPatientInfo} + servicesManager={servicesManager} >
diff --git a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.tsx b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.tsx index f9715783e..ddf3a6d15 100644 --- a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.tsx +++ b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.tsx @@ -401,15 +401,6 @@ function _mapDisplaySets( const imageSrc = thumbnailImageSrcMap[ds.displaySetInstanceUID]; const componentType = _getComponentType(ds); const numPanes = viewportGridService.getNumViewportPanes(); - const viewportIdentificator = []; - - if (numPanes !== 1) { - viewports.forEach(viewportData => { - if (viewportData?.displaySetInstanceUIDs?.includes(ds.displaySetInstanceUID)) { - viewportIdentificator.push(viewportData.viewportLabel); - } - }); - } const array = componentType === 'thumbnailTracked' ? thumbnailDisplaySets : thumbnailNoImageDisplaySets; @@ -435,7 +426,6 @@ function _mapDisplaySets( }, isTracked: trackedSeriesInstanceUIDs.includes(ds.SeriesInstanceUID), isHydratedForDerivedDisplaySet: ds.isHydrated, - viewportIdentificator, }; if (componentType === 'thumbnailNoImage') { diff --git a/extensions/measurement-tracking/src/viewports/TrackedCornerstoneViewport.tsx b/extensions/measurement-tracking/src/viewports/TrackedCornerstoneViewport.tsx index a2026edab..e8400d4a9 100644 --- a/extensions/measurement-tracking/src/viewports/TrackedCornerstoneViewport.tsx +++ b/extensions/measurement-tracking/src/viewports/TrackedCornerstoneViewport.tsx @@ -1,27 +1,29 @@ import React, { useState, useEffect, useCallback } from 'react'; import PropTypes from 'prop-types'; -import OHIF, { utils } from '@ohif/core'; -import { ViewportActionBar, Tooltip, Icon } from '@ohif/ui'; - -import { useTranslation } from 'react-i18next'; +import { Tooltip, Icon, ViewportActionArrows, useViewportGrid } from '@ohif/ui'; import { annotation } from '@cornerstonejs/tools'; import { useTrackedMeasurements } from './../getContextModule'; import { BaseVolumeViewport, Enums } from '@cornerstonejs/core'; - -const { formatDate } = utils; +import { useTranslation } from 'react-i18next'; function TrackedCornerstoneViewport(props) { - const { displaySets, viewportId, viewportLabel, servicesManager, extensionManager } = props; + const { displaySets, viewportId, servicesManager, extensionManager } = props; - const { t } = useTranslation('Common'); - - const { measurementService, cornerstoneViewportService, viewportGridService } = - servicesManager.services; + const { + measurementService, + cornerstoneViewportService, + viewportGridService, + viewportActionCornersService, + } = servicesManager.services; // Todo: handling more than one displaySet on the same viewport const displaySet = displaySets[0]; + const { t } = useTranslation('Common'); + + const [viewportGrid] = useViewportGrid(); + const { activeViewportId } = viewportGrid; const [trackedMeasurements, sendTrackedMeasurementsEvent] = useTrackedMeasurements(); @@ -31,18 +33,7 @@ function TrackedCornerstoneViewport(props) { const { trackedSeries } = trackedMeasurements.context; - const { SeriesDate, SeriesDescription, SeriesInstanceUID, SeriesNumber } = displaySet; - - const { - PatientID, - PatientName, - PatientSex, - PatientAge, - SliceThickness, - SpacingBetweenSlices, - StudyDate, - ManufacturerModelName, - } = displaySet.images[0]; + const { SeriesInstanceUID } = displaySet; const updateIsTracked = useCallback(() => { const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); @@ -170,22 +161,51 @@ function TrackedCornerstoneViewport(props) { }; }, [measurementService, sendTrackedMeasurementsEvent, viewportId, viewportGridService]); - function switchMeasurement(direction) { - const newTrackedMeasurementUID = _getNextMeasurementUID( - direction, - servicesManager, - trackedMeasurementUID, - trackedMeasurements + const switchMeasurement = useCallback( + direction => { + const newTrackedMeasurementUID = _getNextMeasurementUID( + direction, + servicesManager, + trackedMeasurementUID, + trackedMeasurements + ); + + if (!newTrackedMeasurementUID) { + return; + } + + setTrackedMeasurementUID(newTrackedMeasurementUID); + + measurementService.jumpToMeasurement(viewportId, newTrackedMeasurementUID); + }, + [measurementService, servicesManager, trackedMeasurementUID, trackedMeasurements, viewportId] + ); + + useEffect(() => { + const statusComponent = _getStatusComponent(isTracked, t); + const arrowsComponent = _getArrowsComponent( + isTracked, + switchMeasurement, + viewportId === activeViewportId ); - if (!newTrackedMeasurementUID) { - return; - } - - setTrackedMeasurementUID(newTrackedMeasurementUID); - - measurementService.jumpToMeasurement(viewportId, newTrackedMeasurementUID); - } + viewportActionCornersService.setComponents([ + { + viewportId, + id: 'viewportStatusComponent', + component: statusComponent, + indexPriority: -100, + location: viewportActionCornersService.LOCATIONS.topLeft, + }, + { + viewportId, + id: 'viewportActionArrowsComponent', + component: arrowsComponent, + indexPriority: 0, + location: viewportActionCornersService.LOCATIONS.topRight, + }, + ]); + }, [activeViewportId, isTracked, switchMeasurement, viewportActionCornersService, viewportId]); const getCornerstoneViewport = () => { const { component: Component } = extensionManager.getModuleEntry( @@ -203,35 +223,6 @@ function TrackedCornerstoneViewport(props) { return ( <> - { - evt.stopPropagation(); - evt.preventDefault(); - }} - useAltStyling={isTracked} - onArrowsClick={direction => switchMeasurement(direction)} - getStatusComponent={() => _getStatusComponent(isTracked)} - studyData={{ - label: viewportLabel, - studyDate: formatDate(SeriesDate) || formatDate(StudyDate) || t('NoStudyDate'), - currentSeries: SeriesNumber, // TODO - switch entire currentSeries to be UID based or actual position based - seriesDescription: SeriesDescription, - patientInformation: { - patientName: PatientName ? OHIF.utils.formatPN(PatientName) : '', - patientSex: PatientSex || '', - patientAge: PatientAge || '', - MRN: PatientID || '', - thickness: SliceThickness ? `${parseFloat(SliceThickness).toFixed(2)}` : '', - thicknessUnits: t('mm'), - spacing: - SpacingBetweenSlices !== undefined - ? `${parseFloat(SpacingBetweenSlices).toFixed(2)}${t('mm')}` - : '', - scanner: ManufacturerModelName || '', - }, - }} - /> - {/* TODO: Viewport interface to accept stack or layers of content like this? */}
{getCornerstoneViewport()}
@@ -291,18 +282,11 @@ function _getNextMeasurementUID( // Not tracking a measurement, or previous measurement now deleted, revert to 0. measurementIndex = 0; } else { - if (direction === 'left') { - measurementIndex--; - - if (measurementIndex < 0) { - measurementIndex = measurementCount - 1; - } - } else if (direction === 'right') { - measurementIndex++; - - if (measurementIndex === measurementCount) { - measurementIndex = 0; - } + measurementIndex += direction; + if (measurementIndex < 0) { + measurementIndex = measurementCount - 1; + } else if (measurementIndex === measurementCount) { + measurementIndex = 0; } } @@ -311,9 +295,23 @@ function _getNextMeasurementUID( return newTrackedMeasurementId; } -function _getStatusComponent(isTracked) { - const { t } = useTranslation('TrackedCornerstoneViewport'); - const trackedIcon = isTracked ? 'status-tracked' : 'status-untracked'; +const _getArrowsComponent = (isTracked, switchMeasurement, isActiveViewport) => { + if (!isTracked) { + return null; + } + + return ( + switchMeasurement(direction)} + className={isActiveViewport ? 'visible' : 'invisible group-hover:visible'} + > + ); +}; + +function _getStatusComponent(isTracked, t) { + if (!isTracked) { + return null; + } return (
@@ -344,7 +342,7 @@ function _getStatusComponent(isTracked) { } > diff --git a/extensions/tmtv/src/commandsModule.js b/extensions/tmtv/src/commandsModule.js index 32b368b8e..d00b33c89 100644 --- a/extensions/tmtv/src/commandsModule.js +++ b/extensions/tmtv/src/commandsModule.js @@ -508,13 +508,6 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }) displaySetInstanceUID: ptDisplaySet.displaySetInstanceUID, colormap: { name: colormap, - // TODO: This opacity mapping matches that in hpViewports, but - // ideally making this editable in a side panel would be useful - opacity: [ - { value: 0, opacity: 0 }, - { value: 0.1, opacity: 0.9 }, - { value: 1, opacity: 0.95 }, - ], }, }); diff --git a/extensions/tmtv/src/init.js b/extensions/tmtv/src/init.js index 99d4135b6..eaa461533 100644 --- a/extensions/tmtv/src/init.js +++ b/extensions/tmtv/src/init.js @@ -1,10 +1,6 @@ import { addTool, RectangleROIStartEndThresholdTool } from '@cornerstonejs/tools'; -import { utilities } from '@cornerstonejs/core'; import measurementServiceMappingsFactory from './utils/measurementServiceMappings/measurementServiceMappingsFactory'; -import colormaps from './utils/colormaps'; - -const { registerColormap } = utilities.colormap; const CORNERSTONE_3D_TOOLS_SOURCE_NAME = 'Cornerstone3DTools'; const CORNERSTONE_3D_TOOLS_SOURCE_VERSION = '0.1'; @@ -38,5 +34,4 @@ export default function init({ servicesManager }) { RectangleROIStartEndThreshold.toAnnotation, RectangleROIStartEndThreshold.toMeasurement ); - colormaps.forEach(registerColormap); } diff --git a/extensions/tmtv/src/utils/hpViewports.ts b/extensions/tmtv/src/utils/hpViewports.ts index b716a9ef1..a93392170 100644 --- a/extensions/tmtv/src/utils/hpViewports.ts +++ b/extensions/tmtv/src/utils/hpViewports.ts @@ -20,6 +20,9 @@ const ctAXIAL = { id: 'ctWLSync', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -48,6 +51,9 @@ const ctSAGITTAL = { id: 'ctWLSync', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -75,6 +81,9 @@ const ctCORONAL = { id: 'ctWLSync', source: true, target: true, + options: { + syncColormap: true, + }, }, ], }, @@ -108,6 +117,9 @@ const ptAXIAL = { id: 'ptWLSync', source: true, target: true, + options: { + syncColormap: true, + }, }, { type: 'voi', @@ -152,6 +164,9 @@ const ptSAGITTAL = { id: 'ptWLSync', source: true, target: true, + options: { + syncColormap: true, + }, }, { type: 'voi', @@ -196,6 +211,9 @@ const ptCORONAL = { id: 'ptWLSync', source: true, target: true, + options: { + syncColormap: true, + }, }, { type: 'voi', @@ -249,6 +267,9 @@ const fusionAXIAL = { id: 'fusionWLSync', source: true, target: true, + options: { + syncColormap: true, + }, }, { type: 'voi', @@ -312,6 +333,9 @@ const fusionSAGITTAL = { id: 'fusionWLSync', source: true, target: true, + options: { + syncColormap: true, + }, }, { type: 'voi', @@ -375,6 +399,9 @@ const fusionCORONAL = { id: 'fusionWLSync', source: true, target: true, + options: { + syncColormap: true, + }, }, { type: 'voi', @@ -423,6 +450,9 @@ const mipSAGITTAL = { id: 'ptWLSync', source: true, target: true, + options: { + syncColormap: true, + }, }, { type: 'voi', diff --git a/modes/basic-test-mode/src/toolbarButtons.ts b/modes/basic-test-mode/src/toolbarButtons.ts index 81a0ceb57..988e639f7 100644 --- a/modes/basic-test-mode/src/toolbarButtons.ts +++ b/modes/basic-test-mode/src/toolbarButtons.ts @@ -114,7 +114,7 @@ const toolbarButtons: Button[] = [ evaluate: 'evaluate.cornerstoneTool', }, }, - // Window Level + Presets... + // Window Level { id: 'WindowLevel', uiType: 'ohif.splitButton', diff --git a/modes/longitudinal/src/toolbarButtons.ts b/modes/longitudinal/src/toolbarButtons.ts index 55d63b470..bce66af83 100644 --- a/modes/longitudinal/src/toolbarButtons.ts +++ b/modes/longitudinal/src/toolbarButtons.ts @@ -7,29 +7,6 @@ import type { Button } from '@ohif/core/types'; const { windowLevelPresets } = defaults; const { createButton } = ToolbarService; -/** - * - * @param {*} preset - preset number (from above import) - * @param {*} title - * @param {*} subtitle - */ -function _createWwwcPreset(preset, title, subtitle) { - return { - id: preset.toString(), - title, - subtitle, - commands: [ - { - commandName: 'setWindowLevel', - commandOptions: { - ...windowLevelPresets[preset], - }, - context: 'CORNERSTONE', - }, - ], - }; -} - export const setToolActiveToolbar = { commandName: 'setToolActiveToolbar', commandOptions: { @@ -111,33 +88,15 @@ const toolbarButtons: Button[] = [ evaluate: 'evaluate.cornerstoneTool', }, }, - // Window Level + Presets... + // Window Level { id: 'WindowLevel', - uiType: 'ohif.splitButton', + uiType: 'ohif.radioGroup', props: { - groupId: 'WindowLevel', - primary: createButton({ - id: 'WindowLevel', - icon: 'tool-window-level', - label: 'Window Level', - tooltip: 'Window Level', - commands: setToolActiveToolbar, - evaluate: 'evaluate.cornerstoneTool', - }), - secondary: { - icon: 'chevron-down', - label: 'W/L Manual', - tooltip: 'W/L Presets', - }, - renderer: WindowLevelMenuItem, - items: [ - _createWwwcPreset(1, 'Soft tissue', '400 / 40'), - _createWwwcPreset(2, 'Lung', '1500 / -600'), - _createWwwcPreset(3, 'Liver', '150 / 90'), - _createWwwcPreset(4, 'Bone', '2500 / 480'), - _createWwwcPreset(5, 'Brain', '80 / 40'), - ], + icon: 'tool-window-level', + label: 'Window Level', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', }, }, // Pan... diff --git a/modes/segmentation/src/toolbarButtons.ts b/modes/segmentation/src/toolbarButtons.ts index 4d2dacd06..3255570d1 100644 --- a/modes/segmentation/src/toolbarButtons.ts +++ b/modes/segmentation/src/toolbarButtons.ts @@ -49,29 +49,12 @@ const toolbarButtons: Button[] = [ }, { id: 'WindowLevel', - uiType: 'ohif.splitButton', + uiType: 'ohif.radioGroup', props: { - groupId: 'WindowLevel', - primary: createButton({ - id: 'WindowLevel', - icon: 'tool-window-level', - label: 'Window Level', - tooltip: 'Window Level', - commands: setToolActiveToolbar, - evaluate: 'evaluate.cornerstoneTool', - }), - secondary: { - icon: 'chevron-down', - tooltip: 'W/L Presets', - }, - renderer: WindowLevelMenuItem, - items: [ - _createWwwcPreset(1, 'Soft tissue', '400 / 40'), - _createWwwcPreset(2, 'Lung', '1500 / -600'), - _createWwwcPreset(3, 'Liver', '150 / 90'), - _createWwwcPreset(4, 'Bone', '2500 / 480'), - _createWwwcPreset(5, 'Brain', '80 / 40'), - ], + icon: 'tool-window-level', + label: 'Window Level', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', }, }, { diff --git a/modes/tmtv/src/index.js b/modes/tmtv/src/index.js index 92ccb893e..9643fa971 100644 --- a/modes/tmtv/src/index.js +++ b/modes/tmtv/src/index.js @@ -90,7 +90,6 @@ function modeFactory({ modeConfiguration }) { 'Pan', 'SyncToggle', 'RectangleROIStartEndThreshold', - 'fusionPTColormap', ]); // For the hanging protocol we need to decide on the window level diff --git a/modes/tmtv/src/toolbarButtons.js b/modes/tmtv/src/toolbarButtons.js index 5beaac21f..c605b4966 100644 --- a/modes/tmtv/src/toolbarButtons.js +++ b/modes/tmtv/src/toolbarButtons.js @@ -103,29 +103,12 @@ const toolbarButtons = [ // Window Level + Presets { id: 'WindowLevel', - uiType: 'ohif.splitButton', + uiType: 'ohif.radioGroup', props: { - groupId: 'WindowLevel', - primary: ToolbarService.createButton({ - id: 'WindowLevel', - icon: 'tool-window-level', - label: 'Window Level', - tooltip: 'Window Level', - commands: setToolActiveToolbar, - evaluate: 'evaluate.cornerstoneTool', - }), - secondary: { - icon: 'chevron-down', - tooltip: 'W/L Presets', - }, - renderer: WindowLevelMenuItem, - items: [ - _createWwwcPreset(1, 'Soft tissue', '400 / 40'), - _createWwwcPreset(2, 'Lung', '1500 / -600'), - _createWwwcPreset(3, 'Liver', '150 / 90'), - _createWwwcPreset(4, 'Bone', '2500 / 480'), - _createWwwcPreset(5, 'Brain', '80 / 40'), - ], + icon: 'tool-window-level', + label: 'Window Level', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', }, }, // Crosshairs Button @@ -161,38 +144,6 @@ const toolbarButtons = [ evaluate: 'evaluate.cornerstoneTool', }, }, - // Fusion PT Colormap Button - { - id: 'fusionPTColormap', - uiType: 'ohif.splitButton', - props: { - groupId: 'fusionPTColormap', - primary: ToolbarService.createButton({ - id: 'fusionPTColormap', - icon: 'tool-fusion-color', - label: 'Fusion PT Colormap', - tooltip: 'Fusion PT Colormap', - commands: [], - evaluate: 'evaluate.action', - }), - secondary: { - icon: 'chevron-down', - tooltip: 'PET Image Colormap', - }, - items: [ - _createColormap('HSV', 'hsv'), - _createColormap('Hot Iron', 'hot_iron'), - _createColormap('S PET', 's_pet'), - _createColormap('Red Hot', 'red_hot'), - _createColormap('Perfusion', 'perfusion'), - _createColormap('Rainbow', 'rainbow_2'), - _createColormap('SUV', 'suv'), - _createColormap('GE 256', 'ge_256'), - _createColormap('GE', 'ge'), - _createColormap('Siemens', 'siemens'), - ], - }, - }, ]; export default toolbarButtons; diff --git a/platform/app/cypress/integration/MultiStudy.spec.js b/platform/app/cypress/integration/MultiStudy.spec.js index 43fec70cf..3c7da1b37 100644 --- a/platform/app/cypress/integration/MultiStudy.spec.js +++ b/platform/app/cypress/integration/MultiStudy.spec.js @@ -15,7 +15,7 @@ describe('OHIF Multi Study', () => { cy.get('[data-cy="viewport-pane"]').as('viewportPane'); cy.get('@viewportPane').its('length').should('be.eq', 4); - cy.get('[data-cy="studyDate"]').as('studyDate'); + cy.get('[data-cy="viewport-overlay-top-left"] [title="Study date"]').as('studyDate'); cy.get('@studyDate').should(studyDate => { expect(studyDate.length).to.be.eq(4); diff --git a/platform/app/cypress/integration/customization/HangingProtocol.spec.js b/platform/app/cypress/integration/customization/HangingProtocol.spec.js index 4f55e620b..a30064acf 100644 --- a/platform/app/cypress/integration/customization/HangingProtocol.spec.js +++ b/platform/app/cypress/integration/customization/HangingProtocol.spec.js @@ -36,6 +36,6 @@ describe('OHIF HP', () => { cy.initCommonElementsAliases(); // The specified series/sop UID's are index 101, so ensure that image is displayed - cy.get('@viewportInfoTopRight').should('contains.text', 'I:6'); + cy.get('@viewportInfoBottomRight').should('contains.text', 'I:6'); }); }); diff --git a/platform/app/cypress/integration/measurement-tracking/OHIFCornerstoneHotkeys.spec.js b/platform/app/cypress/integration/measurement-tracking/OHIFCornerstoneHotkeys.spec.js index 984b038bc..b0d2f0bd7 100644 --- a/platform/app/cypress/integration/measurement-tracking/OHIFCornerstoneHotkeys.spec.js +++ b/platform/app/cypress/integration/measurement-tracking/OHIFCornerstoneHotkeys.spec.js @@ -29,10 +29,10 @@ describe('OHIF Cornerstone Hotkeys', () => { it('checks if hotkeys "ArrowUp" and "ArrowDown" can navigate in the stack', () => { // Hotkey ArrowDown cy.get('body').type('{downarrow}'); - cy.get('@viewportInfoTopRight').should('contains.text', 'I:2 (2/26)'); + cy.get('@viewportInfoBottomRight').should('contains.text', 'I:2 (2/26)'); // Hotkey ArrowUp cy.get('body').type('{uparrow}'); - cy.get('@viewportInfoTopRight').should('contains.text', 'I:1 (1/26)'); + cy.get('@viewportInfoBottomRight').should('contains.text', 'I:1 (1/26)'); }); it('checks if hotkeys "V" and "H" can flip the image', () => { diff --git a/platform/app/cypress/integration/measurement-tracking/OHIFCornerstoneToolbar.spec.js b/platform/app/cypress/integration/measurement-tracking/OHIFCornerstoneToolbar.spec.js index 45a60fa52..595cfd3dd 100644 --- a/platform/app/cypress/integration/measurement-tracking/OHIFCornerstoneToolbar.spec.js +++ b/platform/app/cypress/integration/measurement-tracking/OHIFCornerstoneToolbar.spec.js @@ -83,7 +83,7 @@ describe('OHIF Cornerstone Toolbar', () => { .trigger('mouseup', { buttons: 1 }); // The exact text is slightly dependent on the viewport resolution, so leave a range - cy.get('@viewportInfoTopLeft').should($txt => { + cy.get('@viewportInfoBottomLeft').should($txt => { const text = $txt.text(); expect(text).to.include('W:118').include('L:479'); }); @@ -143,7 +143,7 @@ describe('OHIF Cornerstone Toolbar', () => { cy.resetViewport(); const expectedText = 'W:958L:479'; - cy.get('@viewportInfoTopLeft').should('have.text', expectedText); + cy.get('@viewportInfoBottomLeft').should('have.text', expectedText); }); /*it('checks if CINE tool will prompt a modal with working controls', () => { diff --git a/platform/app/cypress/integration/measurement-tracking/OHIFGeneralViewer.spec.js b/platform/app/cypress/integration/measurement-tracking/OHIFGeneralViewer.spec.js index f23b2186e..c31a2b76f 100644 --- a/platform/app/cypress/integration/measurement-tracking/OHIFGeneralViewer.spec.js +++ b/platform/app/cypress/integration/measurement-tracking/OHIFGeneralViewer.spec.js @@ -8,7 +8,7 @@ describe('OHIF General Viewer', function () { it('scrolls series stack using scrollbar', function () { cy.scrollToIndex(13); - cy.get('@viewportInfoTopRight').should('contains.text', '14'); + cy.get('@viewportInfoBottomRight').should('contains.text', '14'); }); it('performs right click to zoom', function () { @@ -32,7 +32,7 @@ describe('OHIF General Viewer', function () { .trigger('mouseup'); // make sure the new zoom level is less than the initial - cy.get('@viewportInfoTopLeft').then($viewportInfo => { + cy.get('@viewportInfoBottomLeft').then($viewportInfo => { const zoomLevelFinal = $viewportInfo.text().substring(6, 9); expect(zoomLevelFinal < zoomLevelInitial).to.eq(true); }); diff --git a/platform/app/cypress/integration/measurement-tracking/OHIFMeasurementPanel.spec.js b/platform/app/cypress/integration/measurement-tracking/OHIFMeasurementPanel.spec.js index 435915edf..944f562a6 100644 --- a/platform/app/cypress/integration/measurement-tracking/OHIFMeasurementPanel.spec.js +++ b/platform/app/cypress/integration/measurement-tracking/OHIFMeasurementPanel.spec.js @@ -51,13 +51,13 @@ describe('OHIF Measurement Panel', function () { // Reset to default tool so that the new add length works cy.addLengthMeasurement([100, 100], [200, 200]); //Adding measurement in the viewport - cy.get('@viewportInfoTopRight').should('contains.text', '(14/'); + cy.get('@viewportInfoBottomRight').should('contains.text', '(14/'); // Click on first measurement item cy.get('[data-cy="measurement-item"]').eq(0).click(); - cy.get('@viewportInfoTopRight').should('contains.text', '(1/'); - cy.get('@viewportInfoTopRight').should('not.contains.text', '(14/'); + cy.get('@viewportInfoBottomRight').should('contains.text', '(1/'); + cy.get('@viewportInfoBottomRight').should('not.contains.text', '(14/'); }); /* diff --git a/platform/app/cypress/integration/volume/MPR.spec.js b/platform/app/cypress/integration/volume/MPR.spec.js index 0d15e75e4..2ef026ec9 100644 --- a/platform/app/cypress/integration/volume/MPR.spec.js +++ b/platform/app/cypress/integration/volume/MPR.spec.js @@ -31,31 +31,8 @@ describe('OHIF MPR', () => { cy.wait(250); cy.get('[data-cy="MPR"]').click(); - cy.get('[data-cy="thumbnail-viewport-labels"]').should('have.length', 3); - cy.get('.cornerstone-canvas').should('have.length', 3); - cy.get('[data-cy="thumbnail-viewport-labels"]') - .eq(2) - .find('div') - .should('have.length', 3) - .each(($div, index) => { - const text = $div.text(); - switch (index) { - case 0: - expect(text).to.equal('A'); - break; - case 1: - expect(text).to.equal('B'); - break; - case 2: - expect(text).to.equal('C'); - break; - default: - throw new Error(`Unexpected div found with text: ${text}`); - } - }); - // check cornerstone to see if each has images // we can later do visual testing to match the images with a baseline cy.window() @@ -81,9 +58,6 @@ describe('OHIF MPR', () => { cy.get('[data-cy="MPR"]').click(); cy.get('.cornerstone-canvas').should('have.length', 1); - - // should not have any div under it - cy.get('[data-cy="thumbnail-viewport-labels"]').eq(2).find('div').should('have.length', 0); }); it('should correctly render Crosshairs for MPR', () => { diff --git a/platform/app/src/App.tsx b/platform/app/src/App.tsx index 23b18b2ed..ec170ab40 100644 --- a/platform/app/src/App.tsx +++ b/platform/app/src/App.tsx @@ -5,7 +5,13 @@ import i18n from '@ohif/i18n'; import { I18nextProvider } from 'react-i18next'; import { BrowserRouter } from 'react-router-dom'; import Compose from './routes/Mode/Compose'; -import { ServicesManager, ExtensionManager, CommandsManager, HotkeysManager } from '@ohif/core'; +import { + ServicesManager, + ExtensionManager, + CommandsManager, + HotkeysManager, + ServiceProvidersManager, +} from '@ohif/core'; import { DialogProvider, Modal, @@ -28,6 +34,7 @@ import OpenIdConnectRoutes from './utils/OpenIdConnectRoutes'; let commandsManager: CommandsManager, extensionManager: ExtensionManager, servicesManager: ServicesManager, + serviceProvidersManager: ServiceProvidersManager, hotkeysManager: HotkeysManager; function App({ config, defaultExtensions, defaultModes }) { @@ -48,6 +55,7 @@ function App({ config, defaultExtensions, defaultModes }) { commandsManager = init.commandsManager; extensionManager = init.extensionManager; servicesManager = init.servicesManager; + serviceProvidersManager = init.serviceProvidersManager; hotkeysManager = init.hotkeysManager; // Set appConfig @@ -78,6 +86,15 @@ function App({ config, defaultExtensions, defaultModes }) { [DialogProvider, { service: uiDialogService }], [ModalProvider, { service: uiModalService, modal: Modal }], ]; + + // Loop through and register each of the service providers registered with the ServiceProvidersManager. + const providersFromManager = Object.entries(serviceProvidersManager.providers); + if (providersFromManager.length > 0) { + providersFromManager.forEach(([serviceName, provider]) => { + providers.push([provider, { service: servicesManager.services[serviceName] }]); + }); + } + const CombinedProviders = ({ children }) => Compose({ components: providers, children }); let authRoutes = null; diff --git a/platform/app/src/appInit.js b/platform/app/src/appInit.js index 0d93ae639..867534bd2 100644 --- a/platform/app/src/appInit.js +++ b/platform/app/src/appInit.js @@ -2,6 +2,7 @@ import { CommandsManager, ExtensionManager, ServicesManager, + ServiceProvidersManager, HotkeysManager, UINotificationService, UIModalService, @@ -34,6 +35,7 @@ async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) { const commandsManager = new CommandsManager(commandsManagerConfig); const servicesManager = new ServicesManager(commandsManager); + const serviceProvidersManager = new ServiceProvidersManager(); const hotkeysManager = new HotkeysManager(commandsManager, servicesManager); const appConfig = { @@ -45,6 +47,7 @@ async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) { const extensionManager = new ExtensionManager({ commandsManager, servicesManager, + serviceProvidersManager, hotkeysManager, appConfig, }); @@ -130,6 +133,7 @@ async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) { commandsManager, extensionManager, servicesManager, + serviceProvidersManager, hotkeysManager, }; } diff --git a/platform/app/src/routes/WorkList/WorkList.tsx b/platform/app/src/routes/WorkList/WorkList.tsx index c4c9c6b83..bfa4ecd70 100644 --- a/platform/app/src/routes/WorkList/WorkList.tsx +++ b/platform/app/src/routes/WorkList/WorkList.tsx @@ -32,8 +32,12 @@ import { ButtonEnums, } from '@ohif/ui'; +import { Types } from '@ohif/ui'; + import i18n from '@ohif/i18n'; +const PatientInfoVisibility = Types.PatientInfoVisibility; + const { sortBySeriesDate } = utils; const { availableLanguages, defaultLanguage, currentLanguage } = i18n; @@ -527,6 +531,7 @@ function WorkList({ menuOptions={menuOptions} isReturnEnabled={false} WhiteLabeling={appConfig.whiteLabeling} + showPatientInfo={PatientInfoVisibility.DISABLED} />
diff --git a/platform/core/src/extensions/ExtensionManager.ts b/platform/core/src/extensions/ExtensionManager.ts index 7f6138344..ed4a9c4c5 100644 --- a/platform/core/src/extensions/ExtensionManager.ts +++ b/platform/core/src/extensions/ExtensionManager.ts @@ -1,7 +1,7 @@ import MODULE_TYPES from './MODULE_TYPES'; import log from '../log'; import { AppConfig } from '../types/AppConfig'; -import { PubSubService, ServicesManager } from '../services'; +import { PubSubService, ServiceProvidersManager, ServicesManager } from '../services'; import { HotkeysManager, CommandsManager } from '../classes'; import { DataSourceDefinition } from '../types'; @@ -10,6 +10,7 @@ import { DataSourceDefinition } from '../types'; */ export interface ExtensionConstructor { servicesManager: ServicesManager; + serviceProvidersManager: ServiceProvidersManager; commandsManager: CommandsManager; hotkeysManager: HotkeysManager; appConfig: AppConfig; @@ -28,6 +29,7 @@ export type ExtensionConfiguration = Record; export interface ExtensionParams extends ExtensionConstructor { extensionManager: ExtensionManager; servicesManager: ServicesManager; + serviceProvidersManager: ServiceProvidersManager; configuration?: ExtensionConfiguration; } @@ -71,6 +73,7 @@ export default class ExtensionManager extends PubSubService { private _commandsManager: CommandsManager; private _servicesManager: ServicesManager; private _hotkeysManager: HotkeysManager; + private _serviceProvidersManager: ServiceProvidersManager; private modulesMap: Record; private modules: Record; private registeredExtensionIds: string[]; @@ -88,6 +91,7 @@ export default class ExtensionManager extends PubSubService { constructor({ commandsManager, servicesManager, + serviceProvidersManager, hotkeysManager, appConfig = {}, }: ExtensionConstructor) { @@ -98,6 +102,7 @@ export default class ExtensionManager extends PubSubService { // this._commandsManager = commandsManager; this._servicesManager = servicesManager; + this._serviceProvidersManager = serviceProvidersManager; this._hotkeysManager = hotkeysManager; this._appConfig = appConfig; @@ -256,6 +261,7 @@ export default class ExtensionManager extends PubSubService { if (extension.preRegistration) { await extension.preRegistration({ servicesManager: this._servicesManager, + serviceProvidersManager: this._serviceProvidersManager, commandsManager: this._commandsManager, hotkeysManager: this._hotkeysManager, extensionManager: this, diff --git a/platform/core/src/index.test.js b/platform/core/src/index.test.js index 3c0922200..6b2f6efae 100644 --- a/platform/core/src/index.test.js +++ b/platform/core/src/index.test.js @@ -9,6 +9,7 @@ describe('Top level exports', () => { 'ExtensionManager', 'HotkeysManager', 'ServicesManager', + 'ServiceProvidersManager', // 'defaults', 'utils', diff --git a/platform/core/src/index.ts b/platform/core/src/index.ts index 13612d775..a04b6569f 100644 --- a/platform/core/src/index.ts +++ b/platform/core/src/index.ts @@ -1,5 +1,5 @@ import { ExtensionManager, MODULE_TYPES } from './extensions'; -import { ServicesManager } from './services'; +import { ServiceProvidersManager, ServicesManager } from './services'; import classes, { CommandsManager, HotkeysManager } from './classes'; import DICOMWeb from './DICOMWeb'; @@ -51,6 +51,7 @@ const OHIF = { ExtensionManager, HotkeysManager, ServicesManager, + ServiceProvidersManager, // defaults, utils, @@ -92,6 +93,7 @@ export { ExtensionManager, HotkeysManager, ServicesManager, + ServiceProvidersManager, // defaults, utils, diff --git a/platform/core/src/services/ServiceProvidersManager.ts b/platform/core/src/services/ServiceProvidersManager.ts new file mode 100644 index 000000000..ce2150b6e --- /dev/null +++ b/platform/core/src/services/ServiceProvidersManager.ts @@ -0,0 +1,31 @@ +import log from './../log.js'; + +/** + * The ServiceProvidersManager allows for a React context provider class to be registered + * for a particular service. This allows for extensions to register services + * with context providers and the providers will be instantiated and added to the + * DOM dynamically. + */ +export default class ServiceProvidersManager { + public providers = {}; + + public constructor() { + this.providers = {}; + } + + registerProvider(serviceName, provider) { + if (!serviceName) { + log.warn( + 'Attempting to register a provider to a null/undefined service name. Exiting early.' + ); + return; + } + + if (!provider) { + log.warn('Attempting to register a null/undefined provider. Exiting early.'); + return; + } + + this.providers[serviceName] = provider; + } +} diff --git a/platform/core/src/services/UIModalService/index.ts b/platform/core/src/services/UIModalService/index.ts index 865a2f4b4..eb56bb7ee 100644 --- a/platform/core/src/services/UIModalService/index.ts +++ b/platform/core/src/services/UIModalService/index.ts @@ -42,6 +42,9 @@ class UIModalService { closeButton = true, title = null, customClassName = null, + movable = false, + containerDimensions = null, + contentDimensions = null, }) { return serviceImplementation._show({ content, @@ -51,6 +54,9 @@ class UIModalService { closeButton, title, customClassName, + movable, + containerDimensions, + contentDimensions, }); } diff --git a/platform/core/src/services/index.ts b/platform/core/src/services/index.ts index 3921c7873..bee9afd54 100644 --- a/platform/core/src/services/index.ts +++ b/platform/core/src/services/index.ts @@ -1,5 +1,6 @@ import MeasurementService from './MeasurementService'; import ServicesManager from './ServicesManager'; +import ServiceProvidersManager from './ServiceProvidersManager'; import UIDialogService from './UIDialogService'; import UIModalService from './UIModalService'; import UINotificationService from './UINotificationService'; @@ -22,6 +23,7 @@ export { Services, MeasurementService, ServicesManager, + ServiceProvidersManager, CustomizationService, StateSyncService, UIDialogService, diff --git a/platform/core/src/types/HangingProtocol.ts b/platform/core/src/types/HangingProtocol.ts index 0c0efa512..5fabe5417 100644 --- a/platform/core/src/types/HangingProtocol.ts +++ b/platform/core/src/types/HangingProtocol.ts @@ -133,6 +133,7 @@ export type SyncGroup = { id: string; source?: boolean; target?: boolean; + options?: object; }; /** Declares a custom option, that is a computed type value */ diff --git a/platform/core/src/types/Services.ts b/platform/core/src/types/Services.ts index ece05c32a..bf5d78591 100644 --- a/platform/core/src/types/Services.ts +++ b/platform/core/src/types/Services.ts @@ -33,4 +33,5 @@ export default interface Services { cornerstoneCacheService?: unknown; segmentationService?: unknown; panelService?: unknown; + colorbarService?: unknown; } diff --git a/platform/docs/docs/configuration/configurationFiles.md b/platform/docs/docs/configuration/configurationFiles.md index 959e8d5ae..8182f0c27 100644 --- a/platform/docs/docs/configuration/configurationFiles.md +++ b/platform/docs/docs/configuration/configurationFiles.md @@ -189,6 +189,7 @@ if auth headers are used, a preflight request is required. - `allowMultiSelectExport`: (default to false), if set to true, the user will be able to select the datasource to export the report to. - `activateViewportBeforeInteraction`: (default to true), if set to false, tools can be used directly without the need to click and activate the viewport. - `autoPlayCine`: (default to false), if set to true, data sets with the DICOM frame time tag (i.e. (0018,1063)) will auto play when displayed +- `addWindowLevelActionMenu`: (default to true), if set to false, the window level action menu item is NOT added to the viewport action corners - `dangerouslyUseDynamicConfig`: Dynamic config allows user to pass `configUrl` query string. This allows to load config without recompiling application. If the `configUrl` query string is passed, the worklist and modes will load from the referenced json rather than the default .env config. If there is no `configUrl` path provided, the default behaviour is used and there should not be any deviation from current user experience.
Points to consider while using `dangerouslyUseDynamicConfig`:
- User have to enable this feature by setting `dangerouslyUseDynamicConfig.enabled:true`. By default it is `false`. diff --git a/platform/i18n/src/locales/en-US/Common.json b/platform/i18n/src/locales/en-US/Common.json index 2cbb92cd3..a0b5ce3b4 100644 --- a/platform/i18n/src/locales/en-US/Common.json +++ b/platform/i18n/src/locales/en-US/Common.json @@ -1,4 +1,5 @@ { + "Back to": "Back to {{location}}", "Close": "Close", "Image": "Image", "Layout": "Layout", diff --git a/platform/i18n/src/locales/en-US/WindowLevelActionMenu.json b/platform/i18n/src/locales/en-US/WindowLevelActionMenu.json new file mode 100644 index 000000000..9eba89b7e --- /dev/null +++ b/platform/i18n/src/locales/en-US/WindowLevelActionMenu.json @@ -0,0 +1,5 @@ +{ + "Back to Display Options": "Back to Display Options", + "Modality Presets": "{{modality}} Presets", + "Modality Window Presets": "{{modality}} Window Presets" +} diff --git a/platform/i18n/src/locales/en-US/index.js b/platform/i18n/src/locales/en-US/index.js index eb3d442ba..6004ac655 100644 --- a/platform/i18n/src/locales/en-US/index.js +++ b/platform/i18n/src/locales/en-US/index.js @@ -20,6 +20,7 @@ import TrackedCornerstoneViewport from './TrackedCornerstoneViewport.json'; import UserPreferencesModal from './UserPreferencesModal.json'; import ViewportDownloadForm from './ViewportDownloadForm.json'; import Messages from './Messages.json'; +import WindowLevelActionMenu from './WindowLevelActionMenu.json'; export default { 'en-US': { @@ -45,5 +46,6 @@ export default { UserPreferencesModal, ViewportDownloadForm, Messages, + WindowLevelActionMenu, }, }; diff --git a/platform/i18n/src/locales/test-LNG/WindowLevelActionMenu.json b/platform/i18n/src/locales/test-LNG/WindowLevelActionMenu.json new file mode 100644 index 000000000..13c1c8228 --- /dev/null +++ b/platform/i18n/src/locales/test-LNG/WindowLevelActionMenu.json @@ -0,0 +1,5 @@ +{ + "Back to Display Options": "Test Back to Display Options", + "Modality Presets": "Test {{modality}} Presets", + "Modality Window Presets": "Test {{modality}} Window Presets" +} diff --git a/platform/i18n/src/locales/test-LNG/index.js b/platform/i18n/src/locales/test-LNG/index.js index 561161d2f..16997ce50 100644 --- a/platform/i18n/src/locales/test-LNG/index.js +++ b/platform/i18n/src/locales/test-LNG/index.js @@ -22,6 +22,7 @@ import ThumbnailTracked from './ThumbnailTracked.json'; import TrackedCornerstoneViewport from './TrackedCornerstoneViewport.json'; import UserPreferencesModal from './UserPreferencesModal.json'; import ViewportDownloadForm from './ViewportDownloadForm.json'; +import WindowLevelActionMenu from './WindowLevelActionMenu.json'; export default { 'test-LNG': { @@ -49,5 +50,6 @@ export default { TrackedCornerstoneViewport, UserPreferencesModal, ViewportDownloadForm, + WindowLevelActionMenu, }, }; diff --git a/platform/ui/src/assets/icons/CT-AAA.png b/platform/ui/src/assets/icons/CT-AAA.png new file mode 100644 index 000000000..67c6bf778 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-AAA.png differ diff --git a/platform/ui/src/assets/icons/CT-AAA2.png b/platform/ui/src/assets/icons/CT-AAA2.png new file mode 100644 index 000000000..4c51a6c28 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-AAA2.png differ diff --git a/platform/ui/src/assets/icons/CT-Air.png b/platform/ui/src/assets/icons/CT-Air.png new file mode 100644 index 000000000..a65680aa4 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Air.png differ diff --git a/platform/ui/src/assets/icons/CT-Bone.png b/platform/ui/src/assets/icons/CT-Bone.png new file mode 100644 index 000000000..7c3f8c9ef Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Bone.png differ diff --git a/platform/ui/src/assets/icons/CT-Bones.png b/platform/ui/src/assets/icons/CT-Bones.png new file mode 100644 index 000000000..441d6bf3a Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Bones.png differ diff --git a/platform/ui/src/assets/icons/CT-Cardiac.png b/platform/ui/src/assets/icons/CT-Cardiac.png new file mode 100644 index 000000000..3f9daadb3 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Cardiac.png differ diff --git a/platform/ui/src/assets/icons/CT-Cardiac2.png b/platform/ui/src/assets/icons/CT-Cardiac2.png new file mode 100644 index 000000000..a281b2425 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Cardiac2.png differ diff --git a/platform/ui/src/assets/icons/CT-Cardiac3.png b/platform/ui/src/assets/icons/CT-Cardiac3.png new file mode 100644 index 000000000..0b8773ef8 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Cardiac3.png differ diff --git a/platform/ui/src/assets/icons/CT-Chest-Contrast-Enhanced.png b/platform/ui/src/assets/icons/CT-Chest-Contrast-Enhanced.png new file mode 100644 index 000000000..be165b4c0 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Chest-Contrast-Enhanced.png differ diff --git a/platform/ui/src/assets/icons/CT-Chest-Vessels.png b/platform/ui/src/assets/icons/CT-Chest-Vessels.png new file mode 100644 index 000000000..23f8732c5 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Chest-Vessels.png differ diff --git a/platform/ui/src/assets/icons/CT-Coronary-Arteries-2.png b/platform/ui/src/assets/icons/CT-Coronary-Arteries-2.png new file mode 100644 index 000000000..1b6b16100 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Coronary-Arteries-2.png differ diff --git a/platform/ui/src/assets/icons/CT-Coronary-Arteries-3.png b/platform/ui/src/assets/icons/CT-Coronary-Arteries-3.png new file mode 100644 index 000000000..088a28611 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Coronary-Arteries-3.png differ diff --git a/platform/ui/src/assets/icons/CT-Coronary-Arteries.png b/platform/ui/src/assets/icons/CT-Coronary-Arteries.png new file mode 100644 index 000000000..3b32f1b73 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Coronary-Arteries.png differ diff --git a/platform/ui/src/assets/icons/CT-Cropped-Volume-Bone.png b/platform/ui/src/assets/icons/CT-Cropped-Volume-Bone.png new file mode 100644 index 000000000..13c0922ed Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Cropped-Volume-Bone.png differ diff --git a/platform/ui/src/assets/icons/CT-Fat.png b/platform/ui/src/assets/icons/CT-Fat.png new file mode 100644 index 000000000..9cdd78a25 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Fat.png differ diff --git a/platform/ui/src/assets/icons/CT-Liver-Vasculature.png b/platform/ui/src/assets/icons/CT-Liver-Vasculature.png new file mode 100644 index 000000000..b33856d12 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Liver-Vasculature.png differ diff --git a/platform/ui/src/assets/icons/CT-Lung.png b/platform/ui/src/assets/icons/CT-Lung.png new file mode 100644 index 000000000..158f3d7b2 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Lung.png differ diff --git a/platform/ui/src/assets/icons/CT-MIP.png b/platform/ui/src/assets/icons/CT-MIP.png new file mode 100644 index 000000000..30a93561e Binary files /dev/null and b/platform/ui/src/assets/icons/CT-MIP.png differ diff --git a/platform/ui/src/assets/icons/CT-Muscle.png b/platform/ui/src/assets/icons/CT-Muscle.png new file mode 100644 index 000000000..76ecdc41d Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Muscle.png differ diff --git a/platform/ui/src/assets/icons/CT-Pulmonary-Arteries.png b/platform/ui/src/assets/icons/CT-Pulmonary-Arteries.png new file mode 100644 index 000000000..4558000e0 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Pulmonary-Arteries.png differ diff --git a/platform/ui/src/assets/icons/CT-Soft-Tissue.png b/platform/ui/src/assets/icons/CT-Soft-Tissue.png new file mode 100644 index 000000000..f03690019 Binary files /dev/null and b/platform/ui/src/assets/icons/CT-Soft-Tissue.png differ diff --git a/platform/ui/src/assets/icons/DTI-FA-Brain.png b/platform/ui/src/assets/icons/DTI-FA-Brain.png new file mode 100644 index 000000000..964354622 Binary files /dev/null and b/platform/ui/src/assets/icons/DTI-FA-Brain.png differ diff --git a/platform/ui/src/assets/icons/MR-Angio.png b/platform/ui/src/assets/icons/MR-Angio.png new file mode 100644 index 000000000..f54d6fa5a Binary files /dev/null and b/platform/ui/src/assets/icons/MR-Angio.png differ diff --git a/platform/ui/src/assets/icons/MR-Default.png b/platform/ui/src/assets/icons/MR-Default.png new file mode 100644 index 000000000..f8bf302c1 Binary files /dev/null and b/platform/ui/src/assets/icons/MR-Default.png differ diff --git a/platform/ui/src/assets/icons/MR-MIP.png b/platform/ui/src/assets/icons/MR-MIP.png new file mode 100644 index 000000000..8b3e91a24 Binary files /dev/null and b/platform/ui/src/assets/icons/MR-MIP.png differ diff --git a/platform/ui/src/assets/icons/MR-T2-Brain.png b/platform/ui/src/assets/icons/MR-T2-Brain.png new file mode 100644 index 000000000..8b1f7a550 Binary files /dev/null and b/platform/ui/src/assets/icons/MR-T2-Brain.png differ diff --git a/platform/ui/src/assets/icons/VolumeRendering.png b/platform/ui/src/assets/icons/VolumeRendering.png new file mode 100644 index 000000000..8d7313ea2 Binary files /dev/null and b/platform/ui/src/assets/icons/VolumeRendering.png differ diff --git a/platform/ui/src/assets/icons/action-new-dialog.svg b/platform/ui/src/assets/icons/action-new-dialog.svg new file mode 100644 index 000000000..89331dc6b --- /dev/null +++ b/platform/ui/src/assets/icons/action-new-dialog.svg @@ -0,0 +1,14 @@ + + + action-new-dialog + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/content-next.svg b/platform/ui/src/assets/icons/content-next.svg new file mode 100644 index 000000000..45f0b3985 --- /dev/null +++ b/platform/ui/src/assets/icons/content-next.svg @@ -0,0 +1,9 @@ + + + chevron-next + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/content-prev.svg b/platform/ui/src/assets/icons/content-prev.svg new file mode 100644 index 000000000..a01164b6b --- /dev/null +++ b/platform/ui/src/assets/icons/content-prev.svg @@ -0,0 +1,9 @@ + + + chevron-prev + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/icon-chevron-patient.svg b/platform/ui/src/assets/icons/icon-chevron-patient.svg new file mode 100644 index 000000000..b96478759 --- /dev/null +++ b/platform/ui/src/assets/icons/icon-chevron-patient.svg @@ -0,0 +1,12 @@ + + + icon-chevron-patient + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/icon-color-lut.svg b/platform/ui/src/assets/icons/icon-color-lut.svg new file mode 100644 index 000000000..a339125e7 --- /dev/null +++ b/platform/ui/src/assets/icons/icon-color-lut.svg @@ -0,0 +1,23 @@ + + + icon-color-lut + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/icon-multiple-patients.svg b/platform/ui/src/assets/icons/icon-multiple-patients.svg new file mode 100644 index 000000000..276662f9a --- /dev/null +++ b/platform/ui/src/assets/icons/icon-multiple-patients.svg @@ -0,0 +1,21 @@ + + + icon-multiple-patients + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/icon-patient.svg b/platform/ui/src/assets/icons/icon-patient.svg new file mode 100644 index 000000000..0ddc8f7e6 --- /dev/null +++ b/platform/ui/src/assets/icons/icon-patient.svg @@ -0,0 +1,13 @@ + + + icon-patient + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/icon-settings.svg b/platform/ui/src/assets/icons/icon-settings.svg new file mode 100644 index 000000000..381dae6f2 --- /dev/null +++ b/platform/ui/src/assets/icons/icon-settings.svg @@ -0,0 +1,13 @@ + + + icon-settings + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/icon-toolbar-back.svg b/platform/ui/src/assets/icons/icon-toolbar-back.svg new file mode 100644 index 000000000..8ee453b2c --- /dev/null +++ b/platform/ui/src/assets/icons/icon-toolbar-back.svg @@ -0,0 +1,12 @@ + + + icon-toolbar-back + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/next-arrow.svg b/platform/ui/src/assets/icons/next-arrow.svg new file mode 100644 index 000000000..027a17de3 --- /dev/null +++ b/platform/ui/src/assets/icons/next-arrow.svg @@ -0,0 +1,12 @@ + + + arrow-right + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/prev-arrow.svg b/platform/ui/src/assets/icons/prev-arrow.svg new file mode 100644 index 000000000..455afb6bf --- /dev/null +++ b/platform/ui/src/assets/icons/prev-arrow.svg @@ -0,0 +1,12 @@ + + + arrow-left + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/viewport-status-tracked.svg b/platform/ui/src/assets/icons/viewport-status-tracked.svg new file mode 100644 index 000000000..68185761a --- /dev/null +++ b/platform/ui/src/assets/icons/viewport-status-tracked.svg @@ -0,0 +1,13 @@ + + + viewport-status-tracfked + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/viewport-window-level.svg b/platform/ui/src/assets/icons/viewport-window-level.svg new file mode 100644 index 000000000..ce0a562b2 --- /dev/null +++ b/platform/ui/src/assets/icons/viewport-window-level.svg @@ -0,0 +1,17 @@ + + + viewport-window-level + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/styles/styles.css b/platform/ui/src/assets/styles/styles.css index addaa2375..05abcb151 100644 --- a/platform/ui/src/assets/styles/styles.css +++ b/platform/ui/src/assets/styles/styles.css @@ -1,7 +1,9 @@ /* CUSTOM OHIF SCROLLBAR */ .ohif-scrollbar { - scrollbar-color: #173239 transparent; + scrollbar-color: #041c4a transparent; scrollbar-gutter: stable; + scrollbar-width: thin; + } .study-min-height { @@ -13,7 +15,7 @@ } .ohif-scrollbar::-webkit-scrollbar { - width: 8px; + scrollbar-width: thin; } .ohif-scrollbar::-webkit-scrollbar-track { @@ -22,13 +24,13 @@ .ohif-scrollbar::-webkit-scrollbar-thumb { @apply rounded; - @apply bg-primary-main; - background-color: #173239; + @apply bg-secondary-dark; + background-color: #041c4a; } .ohif-scrollbar::-webkit-scrollbar-thumb:window-inactive { - @apply bg-primary-main; - background-color: #173239; + @apply bg-secondary-dark; + background-color: #041c4a; } /* INVISIBLE SCROLLBAR */ diff --git a/platform/ui/src/assets/svgs/ohif-logo.svg b/platform/ui/src/assets/svgs/ohif-logo.svg new file mode 100644 index 000000000..3692116b4 --- /dev/null +++ b/platform/ui/src/assets/svgs/ohif-logo.svg @@ -0,0 +1,18 @@ + + + toolbar-branding-open-health-imaging-foundation + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/components/AllInOneMenu/BackItem.tsx b/platform/ui/src/components/AllInOneMenu/BackItem.tsx new file mode 100644 index 000000000..ac5ca51b7 --- /dev/null +++ b/platform/ui/src/components/AllInOneMenu/BackItem.tsx @@ -0,0 +1,27 @@ +import React from 'react'; + +import { Icon } from '@ohif/ui'; +import DividerItem from './DividerItem'; + +type BackItemProps = { + backLabel?: string; + onBackClick: () => void; +}; + +const BackItem = ({ backLabel, onBackClick }: BackItemProps) => { + return ( + <> +
+ + +
{backLabel || 'Back to Display Options'}
+
+ + + ); +}; + +export default BackItem; diff --git a/platform/ui/src/components/AllInOneMenu/DividerItem.tsx b/platform/ui/src/components/AllInOneMenu/DividerItem.tsx new file mode 100644 index 000000000..056d68e9c --- /dev/null +++ b/platform/ui/src/components/AllInOneMenu/DividerItem.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +const DividerItem = () => { + return ( +
+
+
+ ); +}; + +export default DividerItem; diff --git a/platform/ui/src/components/AllInOneMenu/HeaderItem.tsx b/platform/ui/src/components/AllInOneMenu/HeaderItem.tsx new file mode 100644 index 000000000..43ba18314 --- /dev/null +++ b/platform/ui/src/components/AllInOneMenu/HeaderItem.tsx @@ -0,0 +1,13 @@ +import React, { ReactNode } from 'react'; + +type HeaderItemProps = { + children: ReactNode; +}; + +const HeaderItem = ({ children }: HeaderItemProps) => { + return ( +
{children}
+ ); +}; + +export default HeaderItem; diff --git a/platform/ui/src/components/AllInOneMenu/IconMenu.tsx b/platform/ui/src/components/AllInOneMenu/IconMenu.tsx new file mode 100644 index 000000000..7b57f6f2f --- /dev/null +++ b/platform/ui/src/components/AllInOneMenu/IconMenu.tsx @@ -0,0 +1,82 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import OutsideClickHandler from 'react-outside-click-handler'; +import { MenuProps } from './Menu'; +import getIcon from '../Icon/getIcon'; +import classNames from 'classnames'; +import { AllInOneMenu } from '..'; +export interface IconMenuProps extends MenuProps { + icon: string; + iconClassName?: string; + horizontalDirection?: AllInOneMenu.HorizontalDirection; + verticalDirection?: AllInOneMenu.VerticalDirection; + menuKey?: number | string; +} + +/** + * An IconMenu allows for a div wrapped icon to be clicked to show and hide + * an AllInOneMenu.Menu. Based on the direction(s) specified, the menu is + * positioned relative to the icon. + * + * HorizontalDirection.LeftToRight - the left edges of the icon and menu are aligned + * HorizontalDirection.RightRoLeft - the right edges of the icon and menu are aligned + * VerticalDirection.TopToBottom - the top edge of the menu appears directly below the bottom edge of the icon + * VerticalDirection.BottomToTop - the bottom edge of the menu appears directly above the top edge of the icon + * + * For example, if an IconMenu were situated in the bottom-left corner of a container, + * it would be best to use BottomToTop and LeftToRight directions for it. + */ +export default function IconMenu({ + icon, + iconClassName, + horizontalDirection, + verticalDirection, + children, + backLabel, + menuClassName, + menuStyle, + onVisibilityChange, + menuKey, +}: IconMenuProps) { + const [isMenuVisible, setIsMenuVisible] = useState(false); + + const toggleMenuVisibility = useCallback(() => setIsMenuVisible(isVisible => !isVisible), []); + + return ( + +
+
+ {getIcon(icon)} +
+ { + setIsMenuVisible(isVis); + onVisibilityChange?.(isVis); + }} + horizontalDirection={horizontalDirection} + > + {children} + +
+
+ ); +} diff --git a/platform/ui/src/components/AllInOneMenu/Item.tsx b/platform/ui/src/components/AllInOneMenu/Item.tsx new file mode 100644 index 000000000..7ad4511a3 --- /dev/null +++ b/platform/ui/src/components/AllInOneMenu/Item.tsx @@ -0,0 +1,45 @@ +import React, { ReactNode, useCallback, useContext } from 'react'; +import { MenuContext } from './Menu'; + +type ItemProps = { + label: string; + secondaryLabel?: string; + icon?: ReactNode; + onClick?: () => void; + onMouseEnter?: () => void; + onMouseLeave?: () => void; + rightIcon?: ReactNode; +}; + +const Item = ({ + label, + secondaryLabel, + icon, + rightIcon, + onClick, + onMouseEnter, + onMouseLeave, +}: ItemProps) => { + const { hideMenu } = useContext(MenuContext); + + const onClickHandler = useCallback(() => { + hideMenu(); + onClick?.(); + }, [hideMenu, onClick]); + + return ( +
+ {icon &&
{icon}
} + {label} + {secondaryLabel != null && {secondaryLabel}} + {rightIcon &&
{rightIcon}
} +
+ ); +}; + +export default Item; diff --git a/platform/ui/src/components/AllInOneMenu/ItemPanel.tsx b/platform/ui/src/components/AllInOneMenu/ItemPanel.tsx new file mode 100644 index 000000000..abe407c7f --- /dev/null +++ b/platform/ui/src/components/AllInOneMenu/ItemPanel.tsx @@ -0,0 +1,29 @@ +import React, { ReactNode, useContext, useEffect } from 'react'; +import { MenuContext } from './Menu'; + +type ItemPanelProps = { + label?: string; + index?: number; + children: ReactNode; +}; + +const ItemPanel = ({ label, index = 0, children }: ItemPanelProps) => { + const { addItemPanel, activePanelIndex } = useContext(MenuContext); + + useEffect(() => { + addItemPanel(index, label); + }, []); + + return ( + activePanelIndex === index && ( +
+ {children} +
+ ) + ); +}; + +export default ItemPanel; diff --git a/platform/ui/src/components/AllInOneMenu/Menu.tsx b/platform/ui/src/components/AllInOneMenu/Menu.tsx new file mode 100644 index 000000000..7e506496b --- /dev/null +++ b/platform/ui/src/components/AllInOneMenu/Menu.tsx @@ -0,0 +1,188 @@ +import React, { createContext, ReactNode, useCallback, useEffect, useState } from 'react'; + +import './allInOneMenu.css'; +import DividerItem from './DividerItem'; +import PanelSelector from './PanelSelector'; +import classNames from 'classnames'; +import BackItem from './BackItem'; + +/** + * The vertical direction that the menu will be opened/used with. + * + * A TopToBottom menu would be used for cases where the menu is opened "near" + * the top edge of its container. Likewise a BottomToTop menu would be used + * for cases where the menu is opened "near" the bottom edge of its container. + * + * See IconMenu for more information. + */ +export enum VerticalDirection { + TopToBottom, + BottomToTop, +} + +/** + * The horizontal direction that the menu is opened/used with. + * This direction dictates the general direction sub-menus and + * back-to-menus are opened with. For example, a RightToLeft menu + * will have sub-menu items indicated with a left pointing chevron + * and aligned with the left edge of the menu. Similarly back-to items of a + * RightToLeft menu are indicated with a right pointing chevron and + * aligned with the right edge of the menu. + * + * It is also worth noting that a LeftToRight menu would be used for + * cases where a menu is opened "near" the left edge of its container. + * Likewise, a RightToLeft menu would be used for cases where a menu is opened + * "near" the right edge of its container. + * + * See IconMenu for more information. + */ +export enum HorizontalDirection { + LeftToRight, + RightToLeft, +} + +export interface MenuProps { + menuStyle?: unknown; + menuClassName?: string; + isVisible?: boolean; + preventHideMenu?: boolean; + backLabel?: string; + headerComponent?: ReactNode; + showHeaderDivider?: boolean; + activePanelIndex?: number; + onVisibilityChange?: (isVisible: boolean) => void; + horizontalDirection?: HorizontalDirection; + children: ReactNode; +} +type MenuContextProps = { + showSubMenu: (subMenuProps: MenuProps) => void; + hideMenu: () => void; + addItemPanel: (index: number, label: string) => void; + horizontalDirection: HorizontalDirection; + activePanelIndex: number; +}; + +type MenuPathState = { + props: MenuProps; + activePanelIndex: number; +}; + +export const MenuContext = createContext(null); + +const Menu = (props: MenuProps) => { + const { + isVisible, + onVisibilityChange, + activePanelIndex, + preventHideMenu, + menuClassName, + menuStyle, + horizontalDirection = HorizontalDirection.LeftToRight, + } = props; + + const [isMenuVisible, setIsMenuVisible] = useState(isVisible); + + // The menuPath is an array consisting of this top Menu and every SubMenu + // that has been traversed/opened by the user with the last item in the array + // being the current (sub)menu that is currently visible. This allows for the previously + // viewed menus to be returned to via the Back button at the top of the menu. + const [menuPath, setMenuPath] = useState>([ + { props, activePanelIndex: activePanelIndex || 0 }, + ]); + const [itemPanelLabels, setItemPanelLabels] = useState>([]); + + const hideMenu = useCallback(() => { + if (preventHideMenu) { + return; + } + setMenuPath(path => [path[0]]); + setItemPanelLabels([]); + setIsMenuVisible(false); + onVisibilityChange?.(false); + }, [preventHideMenu, onVisibilityChange]); + + useEffect(() => { + if (isVisible) { + setIsMenuVisible(isVisible); + onVisibilityChange?.(isVisible); + } else { + hideMenu(); + } + }, [hideMenu, isVisible, onVisibilityChange]); + + const showSubMenu = useCallback((subMenuProps: MenuProps) => { + setMenuPath(path => { + return [ + ...path, + { props: subMenuProps, activePanelIndex: subMenuProps.activePanelIndex || 0 }, + ]; + }); + setItemPanelLabels([]); + }, []); + + const addItemPanel = useCallback((index, label) => { + setItemPanelLabels(labels => { + return [...labels.slice(0, index), label, ...labels.slice(index + 1, labels.length)]; + }); + }, []); + + const onActivePanelIndexChange = useCallback(index => { + setMenuPath(path => { + return [ + ...path.slice(0, path.length - 1), + { ...path[path.length - 1], activePanelIndex: index }, + ]; + }); + }, []); + + const onBackClick = useCallback(() => { + setMenuPath(path => [...path.slice(0, path.length - 1)]); + setItemPanelLabels([]); + }, []); + + const { props: currentMenuProps, activePanelIndex: currentMenuActivePanelIndex } = + menuPath[menuPath.length - 1]; + + return ( + <> + + {isMenuVisible && ( +
+ {menuPath.length > 1 && ( + + )} + {itemPanelLabels.length > 1 && ( + + )} + {currentMenuProps.headerComponent} + {currentMenuProps.showHeaderDivider && } + {currentMenuProps.children} +
+ )} +
+ + ); +}; + +export default Menu; diff --git a/platform/ui/src/components/AllInOneMenu/PanelSelector.tsx b/platform/ui/src/components/AllInOneMenu/PanelSelector.tsx new file mode 100644 index 000000000..c46207b54 --- /dev/null +++ b/platform/ui/src/components/AllInOneMenu/PanelSelector.tsx @@ -0,0 +1,31 @@ +import React, { ReactNode } from 'react'; +import { ButtonGroup } from '../../components'; + +type PanelSelectorProps = { + panelLabels: Array; + onActiveIndexChange: (index: number) => void; + activeIndex: number; +}; + +const PanelSelector = ({ panelLabels, onActiveIndexChange, activeIndex }: PanelSelectorProps) => { + const getButtons = () => { + return panelLabels.map((panelLabel, index) => { + return { + children: panelLabel, + key: index, + }; + }); + }; + + return ( +
+ +
+ ); +}; + +export default PanelSelector; diff --git a/platform/ui/src/components/AllInOneMenu/SubMenu.tsx b/platform/ui/src/components/AllInOneMenu/SubMenu.tsx new file mode 100644 index 000000000..42786622a --- /dev/null +++ b/platform/ui/src/components/AllInOneMenu/SubMenu.tsx @@ -0,0 +1,38 @@ +import React, { useCallback, useContext } from 'react'; +import { MenuContext, MenuProps } from './Menu'; +import Icon from '../Icon'; + +export interface SubMenuProps extends MenuProps { + itemLabel: string; + onClick?: () => void; + itemIcon?: string; +} + +const SubMenu = (props: SubMenuProps) => { + const { showSubMenu } = useContext(MenuContext); + + const onClickHandler = useCallback(() => { + showSubMenu(props); + props.onClick?.(); + }, [showSubMenu, props]); + + return ( +
+ {props.itemIcon && ( + + )} +
{props.itemLabel}
+ +
+ ); +}; + +export default SubMenu; diff --git a/platform/ui/src/components/AllInOneMenu/__stories__/allInOneMenu.stories.mdx b/platform/ui/src/components/AllInOneMenu/__stories__/allInOneMenu.stories.mdx new file mode 100644 index 000000000..a513dc672 --- /dev/null +++ b/platform/ui/src/components/AllInOneMenu/__stories__/allInOneMenu.stories.mdx @@ -0,0 +1,129 @@ +import { DividerItem, HeaderItem, Item, ItemPanel, Menu, SubMenu } from '..'; +import InputRange from '../../InputRange/index.js'; +import SwitchButton from '../../SwitchButton/index.js'; + +import { ArgsTable, Story, Canvas, Meta } from '@storybook/addon-docs'; + +export const argTypes = { + component: Menu, + title: 'Components/AllInOneMenu', +}; + + + +export const AllInOneMenuTemplate = args => ( +
+ + + console.info('Item 1 clicked.')} + > + +
+
Arbitrary item component:
+ {}} + > +
+ + console.info('Sub menu item clicked.')} + showHeaderDivider={true} + headerComponent={ +
+ +
+ } + > + + + + + + Header for scrolling list of items} + > + + + + + + + + + + +
+
+
+
+); + + + +- [Overview](#overview) +- [Props](#props) +- [Contribute](#contribute) + +## Overview + +AllInOneMenu is a component that renders a menu with various menu items, sub-menus and +sub-components. The particular feature of the AllInOneMenu is its ability to render a sub-menu by +replacing the parent menu on screen. It also provides the ability to return to the parent menu with +a back menu item from the sub-menu. Furthermore, each menu level can be split into item panes - that +is several panes of menu items that are switched in and out of view like a tabbed pane. + + + console.info(`The menu visibility: ${isVisible}`), + }} +> + + {AllInOneMenuTemplate.bind({})} + + + + +## Props + + + +## Usage + +## Contribute + +
diff --git a/platform/ui/src/components/AllInOneMenu/allInOneMenu.css b/platform/ui/src/components/AllInOneMenu/allInOneMenu.css new file mode 100644 index 000000000..ce8ea955c --- /dev/null +++ b/platform/ui/src/components/AllInOneMenu/allInOneMenu.css @@ -0,0 +1,11 @@ +.all-in-one-menu-item { + @apply h-8 px-2 text-[14px] w-full; + display: flex; + align-items: center; + flex-shrink: 0; + line-height: 18px; +} + +.all-in-one-menu-item-effects { + @apply cursor-pointer hover:bg-primary-dark hover:rounded; +} diff --git a/platform/ui/src/components/AllInOneMenu/index.tsx b/platform/ui/src/components/AllInOneMenu/index.tsx new file mode 100644 index 000000000..f0522cf86 --- /dev/null +++ b/platform/ui/src/components/AllInOneMenu/index.tsx @@ -0,0 +1,19 @@ +import Menu, { HorizontalDirection, VerticalDirection } from './Menu'; +import DividerItem from './DividerItem'; +import HeaderItem from './HeaderItem'; +import IconMenu from './IconMenu'; +import Item from './Item'; +import ItemPanel from './ItemPanel'; +import SubMenu from './SubMenu'; + +export { + Menu, + DividerItem, + HeaderItem, + IconMenu, + Item, + ItemPanel, + SubMenu, + HorizontalDirection, + VerticalDirection, +}; diff --git a/platform/ui/src/components/ButtonGroup/ButtonGroup.tsx b/platform/ui/src/components/ButtonGroup/ButtonGroup.tsx index d47288bf2..ca080a138 100644 --- a/platform/ui/src/components/ButtonGroup/ButtonGroup.tsx +++ b/platform/ui/src/components/ButtonGroup/ButtonGroup.tsx @@ -41,7 +41,7 @@ const ButtonGroup = ({ return cloneElement(child, { key: index, className: classnames( - 'rounded-[4px] px-2 py-1', + 'rounded-[4px] px-2 py-1 text-center', index === activeIndex ? 'bg-customblue-40 text-white' : 'text-primary-active bg-black', diff --git a/platform/ui/src/components/Header/Header.tsx b/platform/ui/src/components/Header/Header.tsx index 99b97b527..5d4cd63e9 100644 --- a/platform/ui/src/components/Header/Header.tsx +++ b/platform/ui/src/components/Header/Header.tsx @@ -8,6 +8,8 @@ import Svg from '../Svg'; import Icon from '../Icon'; import IconButton from '../IconButton'; import Dropdown from '../Dropdown'; +import HeaderPatientInfo from '../HeaderPatientInfo'; +import { PatientInfoVisibility } from '../../types/PatientInfoVisibility'; function Header({ children, @@ -16,6 +18,8 @@ function Header({ onClickReturnButton, isSticky, WhiteLabeling, + showPatientInfo = PatientInfoVisibility.VISIBLE_COLLAPSED, + servicesManager, ...props }): ReactNode { const { t } = useTranslation('Header'); @@ -34,7 +38,7 @@ function Header({ {...props} >
-
+
)} -
+
{WhiteLabeling?.createLogoComponentFn?.(React, props) || }
@@ -58,32 +62,30 @@ function Header({
{children}
-
- - + {(showPatientInfo === PatientInfoVisibility.VISIBLE || + showPatientInfo === PatientInfoVisibility.VISIBLE_COLLAPSED) && ( + + )} +
+
+ - - - - - - + + + + +
@@ -103,6 +105,8 @@ Header.propTypes = { isSticky: PropTypes.bool, onClickReturnButton: PropTypes.func, WhiteLabeling: PropTypes.object, + showPatientInfo: PropTypes.string, + servicesManager: PropTypes.object, }; Header.defaultProps = { diff --git a/platform/ui/src/components/HeaderPatientInfo/HeaderPatientInfo.tsx b/platform/ui/src/components/HeaderPatientInfo/HeaderPatientInfo.tsx new file mode 100644 index 000000000..ec665a7a9 --- /dev/null +++ b/platform/ui/src/components/HeaderPatientInfo/HeaderPatientInfo.tsx @@ -0,0 +1,134 @@ +import React, { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import { Icon } from '@ohif/ui'; +import { utils } from '@ohif/core'; +import { useAppConfig } from '@state'; + +const { formatDate, formatPN } = utils; + +const formatWithEllipsis = (str, maxLength) => { + if (str.length > maxLength) { + return str.substring(0, maxLength) + '...'; + } + return str; +}; + +function usePatientInfo(servicesManager) { + const { displaySetService } = servicesManager.services; + + const [patientInfo, setPatientInfo] = useState({ + PatientName: '', + PatientID: '', + PatientSex: '', + PatientDOB: '', + }); + const [isMixedPatients, setIsMixedPatients] = useState(false); + const displaySets = displaySetService.getActiveDisplaySets(); + + const checkMixedPatients = PatientID => { + const displaySets = displaySetService.getActiveDisplaySets(); + let isMixedPatients = false; + displaySets.forEach(displaySet => { + const instance = displaySet?.instances?.[0] || displaySet?.instance; + if (!instance) { + return; + } + if (instance.PatientID !== PatientID) { + isMixedPatients = true; + } + }); + setIsMixedPatients(isMixedPatients); + }; + + const updatePatientInfo = () => { + const displaySet = displaySets[0]; + const instance = displaySet?.instances?.[0] || displaySet?.instance; + if (!instance) { + return; + } + setPatientInfo({ + PatientID: instance.PatientID || '', + PatientName: instance.PatientName ? formatPN(instance.PatientName.Alphabetic) : '', + PatientSex: instance.PatientSex || '', + PatientDOB: formatDate(instance.PatientBirthDate) || '', + }); + checkMixedPatients(instance.PatientID || ''); + }; + + useEffect(() => { + const subscription = displaySetService.subscribe( + displaySetService.EVENTS.DISPLAY_SETS_ADDED, + () => updatePatientInfo() + ); + return () => subscription.unsubscribe(); + }, []); + + useEffect(() => { + updatePatientInfo(); + }, [displaySets]); + + return { patientInfo, isMixedPatients }; +} + +function HeaderPatientInfo({ servicesManager }) { + const [appConfig] = useAppConfig(); + const initialExpandedState = appConfig.showPatientInfo === 'visible'; + const [expanded, setExpanded] = useState(initialExpandedState); + const { patientInfo, isMixedPatients } = usePatientInfo(servicesManager); + + useEffect(() => { + if (isMixedPatients && expanded) { + setExpanded(false); + } + }, [isMixedPatients, expanded]); + + const handleOnClick = () => { + if (!isMixedPatients) { + setExpanded(!expanded); + } + }; + + const formattedPatientName = formatWithEllipsis(patientInfo.PatientName, 27); + const formattedPatientID = formatWithEllipsis(patientInfo.PatientID, 15); + + return ( +
+ +
+ {expanded ? ( + <> +
+ {formattedPatientName} +
+
+
{formattedPatientID}
+
{patientInfo.PatientSex}
+
{patientInfo.PatientDOB}
+
+ + ) : ( +
+ {' '} + {isMixedPatients ? 'Multiple Patients' : 'Patient'} +
+ )} +
+ +
+ ); +} + +HeaderPatientInfo.propTypes = { + servicesManager: PropTypes.object.isRequired, +}; + +export default HeaderPatientInfo; diff --git a/platform/ui/src/components/HeaderPatientInfo/index.js b/platform/ui/src/components/HeaderPatientInfo/index.js new file mode 100644 index 000000000..cc989ba53 --- /dev/null +++ b/platform/ui/src/components/HeaderPatientInfo/index.js @@ -0,0 +1,3 @@ +import HeaderPatientInfo from './HeaderPatientInfo'; + +export default HeaderPatientInfo; diff --git a/platform/ui/src/components/Icon/getIcon.js b/platform/ui/src/components/Icon/getIcon.js index 4940fb771..e02d77b20 100644 --- a/platform/ui/src/components/Icon/getIcon.js +++ b/platform/ui/src/components/Icon/getIcon.js @@ -17,6 +17,8 @@ import chevronMenu from './../../assets/icons/chevron-menu.svg'; import chevronNext from './../../assets/icons/chevron-next.svg'; import chevronPrev from './../../assets/icons/chevron-prev.svg'; import chevronRight from './../../assets/icons/chevron-right.svg'; +import contentNext from './../../assets/icons/content-next.svg'; +import contentPrev from './../../assets/icons/content-prev.svg'; import eyeVisible from './../../assets/icons/eye-visible.svg'; import eyeHidden from './../../assets/icons/eye-hidden.svg'; import exclamation from './../../assets/icons/exclamation.svg'; @@ -83,6 +85,9 @@ import notificationsInfo from './../../assets/icons/notifications-info.svg'; import notificationsWarning from './../../assets/icons/notifications-warning.svg'; import notificationsError from './../../assets/icons/notifications-error.svg'; import notificationsSuccess from './../../assets/icons/notifications-success.svg'; +import nextArrow from './../../assets/icons/next-arrow.svg'; +import prevArrow from './../../assets/icons/prev-arrow.svg'; +import viewportStatusTracked from './../../assets/icons/viewport-status-tracked.svg'; /** Tools */ import toggleDicomOverlay from './../../assets/icons/toggle-dicom-overlay.svg'; @@ -139,12 +144,53 @@ import iconToolEraser from './../../assets/icons/icon-tool-eraser.svg'; import iconToolScissor from './../../assets/icons/icon-tool-scissor.svg'; import iconToolShape from './../../assets/icons/icon-tool-shape.svg'; import iconToolThreshold from './../../assets/icons/icon-tool-threshold.svg'; +import viewportWindowLevel from './../../assets/icons/viewport-window-level.svg'; /** Old OHIF */ import oldTrash from './../../assets/icons/old-trash.svg'; import oldPlay from './../../assets/icons/old-play.svg'; import oldStop from './../../assets/icons/old-stop.svg'; +/** ColorLut */ +import iconColorLUT from './../../assets/icons/icon-color-lut.svg'; + +/** New Patient Info Toolbar */ +import iconChevronPatient from './../../assets/icons/icon-chevron-patient.svg'; +import iconPatient from './../../assets/icons/icon-patient.svg'; +import iconSettings from './../../assets/icons/icon-settings.svg'; +import iconToolbarBack from './../../assets/icons/icon-toolbar-back.svg'; +import iconMultiplePatients from './../../assets/icons/icon-multiple-patients.svg'; + +/** Volume Rendering */ +import CTAAA from './../../assets/icons/CT-AAA.png'; +import CTAAA2 from './../../assets/icons/CT-AAA2.png'; +import CTAir from './../../assets/icons/CT-Air.png'; +import CTBone from './../../assets/icons/CT-Bone.png'; +import CTBones from './../../assets/icons/CT-Bones.png'; +import CTCardiac from './../../assets/icons/CT-Cardiac.png'; +import CTCardiac2 from './../../assets/icons/CT-Cardiac2.png'; +import CTCardiac3 from './../../assets/icons/CT-Cardiac3.png'; +import CTChestContrastEnhanced from './../../assets/icons/CT-Chest-Contrast-Enhanced.png'; +import CTChestVessels from './../../assets/icons/CT-Chest-Vessels.png'; +import CTCoronaryArteries from './../../assets/icons/CT-Coronary-Arteries.png'; +import CTCoronaryArteries2 from './../../assets/icons/CT-Coronary-Arteries-2.png'; +import CTCoronaryArteries3 from './../../assets/icons/CT-Coronary-Arteries-3.png'; +import CTCroppedVolumeBone from './../../assets/icons/CT-Cropped-Volume-Bone.png'; +import CTFat from './../../assets/icons/CT-Fat.png'; +import CTLiverVasculature from './../../assets/icons/CT-Liver-Vasculature.png'; +import CTLung from './../../assets/icons/CT-Lung.png'; +import CTMIP from './../../assets/icons/CT-MIP.png'; +import CTMuscle from './../../assets/icons/CT-Muscle.png'; +import CTPulmonaryArteries from './../../assets/icons/CT-Pulmonary-Arteries.png'; +import CTSoftTissue from './../../assets/icons/CT-Soft-Tissue.png'; +import DTIFABrain from './../../assets/icons/DTI-FA-Brain.png'; +import MRAngio from './../../assets/icons/MR-Angio.png'; +import MRDefault from './../../assets/icons/MR-Default.png'; +import MRMIP from './../../assets/icons/MR-MIP.png'; +import MRT2Brain from './../../assets/icons/MR-T2-Brain.png'; +import VolumeRendering from './../../assets/icons/VolumeRendering.png'; +import actionNewDialog from './../../assets/icons/action-new-dialog.svg'; + /** LAYOUT */ import layoutAdvanced3DFourUp from './../../assets/icons/layout-advanced-3d-four-up.svg'; @@ -160,7 +206,6 @@ import layoutCommon2x3 from './../../assets/icons/layout-common-2x3.svg'; import iconToolRotate from './../../assets/icons/tool-3d-rotate.svg'; /** New investigational use */ - import investigationalUse from './../../assets/icons/illustration-investigational-use.svg'; const ICONS = { @@ -180,6 +225,8 @@ const ICONS = { 'chevron-next': chevronNext, 'chevron-prev': chevronPrev, 'chevron-right': chevronRight, + 'content-next': contentNext, + 'content-prev': contentPrev, 'eye-visible': eyeVisible, 'eye-hidden': eyeHidden, 'external-link': externalLink, @@ -304,12 +351,51 @@ const ICONS = { 'icon-tool-scissor': iconToolScissor, 'icon-tool-shape': iconToolShape, 'icon-tool-threshold': iconToolThreshold, - + 'next-arrow': nextArrow, + 'prev-arrow': prevArrow, + 'viewport-status-tracked': viewportStatusTracked, + 'viewport-window-level': viewportWindowLevel, /** Old OHIF */ 'old-trash': oldTrash, 'old-play': oldPlay, 'old-stop': oldStop, - + /** ColorLut */ + 'icon-color-lut': iconColorLUT, + /** New Patient Info Toolbar */ + 'icon-chevron-patient': iconChevronPatient, + 'icon-patient': iconPatient, + 'icon-settings': iconSettings, + 'icon-toolbar-back': iconToolbarBack, + 'icon-multiple-patients': iconMultiplePatients, + /** Volume Rendering */ + 'CT-AAA': CTAAA, + 'CT-AAA2': CTAAA2, + 'CT-Air': CTAir, + 'CT-Bone': CTBone, + 'CT-Bones': CTBones, + 'CT-Cardiac': CTCardiac, + 'CT-Cardiac2': CTCardiac2, + 'CT-Cardiac3': CTCardiac3, + 'CT-Chest-Contrast-Enhanced': CTChestContrastEnhanced, + 'CT-Chest-Vessels': CTChestVessels, + 'CT-Coronary-Arteries': CTCoronaryArteries, + 'CT-Coronary-Arteries-2': CTCoronaryArteries2, + 'CT-Coronary-Arteries-3': CTCoronaryArteries3, + 'CT-Cropped-Volume-Bone': CTCroppedVolumeBone, + 'CT-Fat': CTFat, + 'CT-Liver-Vasculature': CTLiverVasculature, + 'CT-Lung': CTLung, + 'CT-MIP': CTMIP, + 'CT-Muscle': CTMuscle, + 'CT-Pulmonary-Arteries': CTPulmonaryArteries, + 'CT-Soft-Tissue': CTSoftTissue, + 'DTI-FA-Brain': DTIFABrain, + 'MR-Angio': MRAngio, + 'MR-Default': MRDefault, + 'MR-MIP': MRMIP, + 'MR-T2-Brain': MRT2Brain, + VolumeRendering: VolumeRendering, + 'action-new-dialog': actionNewDialog, /** LAYOUT */ 'layout-advanced-3d-four-up': layoutAdvanced3DFourUp, 'layout-advanced-3d-main': layoutAdvanced3DMain, @@ -340,11 +426,17 @@ function addIcon(iconName, iconSVG) { * return `null` */ export default function getIcon(key, props) { - if (!key || !ICONS[key]) { + const icon = ICONS[key]; + + if (!key || !icon) { return React.createElement('div', null, 'Missing Icon'); } - return React.createElement(ICONS[key], props); + if (typeof icon === 'string' && icon.endsWith('.png')) { + return React.createElement('img', { src: icon, ...props }); + } else { + return React.createElement(icon, props); + } } export { getIcon, ICONS, addIcon }; diff --git a/platform/ui/src/components/ImageScrollbar/ImageScrollbar.css b/platform/ui/src/components/ImageScrollbar/ImageScrollbar.css index 6d1aaf32d..695e11e9c 100644 --- a/platform/ui/src/components/ImageScrollbar/ImageScrollbar.css +++ b/platform/ui/src/components/ImageScrollbar/ImageScrollbar.css @@ -1,13 +1,13 @@ .scroll { - height: 100%; + height: calc(100% - 30px); padding: 5px; position: absolute; right: 0; - top: 0; + top: 30px; } .scroll .scroll-holder { - height: calc(100% - 20px); - margin-top: 5px; + height: calc(100%); + margin-bottom: 5px; position: relative; width: 12px; } diff --git a/platform/ui/src/components/InputRange/InputRange.tsx b/platform/ui/src/components/InputRange/InputRange.tsx index 8986143a9..4ae168712 100644 --- a/platform/ui/src/components/InputRange/InputRange.tsx +++ b/platform/ui/src/components/InputRange/InputRange.tsx @@ -12,6 +12,12 @@ import getMaxDigits from '../../utils/getMaxDigits'; * * */ + +type Label = { + text: string; + position: number; +}; + type InputRangeProps = { value: number; onChange: (value: number) => void; @@ -28,6 +34,7 @@ type InputRangeProps = { trackColor?: string; allowNumberEdit?: boolean; showAdjustmentArrows?: boolean; + labels?: Label[]; }; const InputRange: React.FC = ({ @@ -46,6 +53,7 @@ const InputRange: React.FC = ({ trackColor, allowNumberEdit = false, showAdjustmentArrows = true, + labels = [], }) => { const [rangeValue, setRangeValue] = useState(value); @@ -114,6 +122,22 @@ const InputRange: React.FC = ({ {showLabel && labelPosition === 'right' && (
{LabelOrEditableNumber}
)} + {labels.length > 0 && ( + <> + {labels.map((label, index) => { + const position = label.position; + return ( +
+ {label.text} +
+ ); + })} + + )}
); diff --git a/platform/ui/src/components/Modal/Modal.tsx b/platform/ui/src/components/Modal/Modal.tsx index 783f9c9fb..1a717dc10 100644 --- a/platform/ui/src/components/Modal/Modal.tsx +++ b/platform/ui/src/components/Modal/Modal.tsx @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import ReactModal from 'react-modal'; +import Draggable from 'react-draggable'; import { useModal } from '../../contextProviders'; import Icon from '../Icon'; @@ -20,6 +21,9 @@ const Modal = ({ onClose, children, shouldCloseOnOverlayClick, + movable = false, + containerDimensions = null, + contentDimensions = null, }) => { const { hide } = useModal(); @@ -27,44 +31,70 @@ const Modal = ({ hide(); }; - const renderHeader = () => { - return ( - title && ( -
- - {title} - - {closeButton && ( - - )} -
- ) + const renderHeader = () => + title && ( +
+ + {title} + + {closeButton && ( + + )} +
); - }; + + const modalContent = ( + <> + {renderHeader()} +
+ {children} +
+ + ); return ( - {renderHeader()} -
- {children} -
+ {movable ? ( + +
{modalContent}
+
+ ) : ( + modalContent + )}
); }; @@ -72,6 +102,9 @@ const Modal = ({ Modal.defaultProps = { shouldCloseOnEsc: true, shouldCloseOnOverlayClick: true, + movable: false, + containerDimensions: null, + contentDimensions: null, }; Modal.propTypes = { @@ -80,9 +113,11 @@ Modal.propTypes = { isOpen: PropTypes.bool, title: PropTypes.string, onClose: PropTypes.func, - /** The modal's content */ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired, shouldCloseOnOverlayClick: PropTypes.bool, + movable: PropTypes.bool, + containerDimensions: PropTypes.string, + contentDimensions: PropTypes.string, }; export default Modal; diff --git a/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx b/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx index 671f1f628..c212de7ff 100644 --- a/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx +++ b/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx @@ -149,7 +149,6 @@ StudyBrowser.propTypes = { componentType: PropTypes.oneOf(['thumbnail', 'thumbnailTracked', 'thumbnailNoImage']) .isRequired, isTracked: PropTypes.bool, - viewportIdentificator: PropTypes.arrayOf(PropTypes.string), /** * Data the thumbnail should expose to a receiving drop target. Use a matching * `dragData.type` to identify which targets can receive this draggable item. diff --git a/platform/ui/src/components/StudyBrowser/__stories__/studyBrowser.stories.mdx b/platform/ui/src/components/StudyBrowser/__stories__/studyBrowser.stories.mdx index e60692f3f..0c0c10132 100644 --- a/platform/ui/src/components/StudyBrowser/__stories__/studyBrowser.stories.mdx +++ b/platform/ui/src/components/StudyBrowser/__stories__/studyBrowser.stories.mdx @@ -99,7 +99,6 @@ With Studies displaySetInstanceUID: '0b66675a-a4e3-a718-21f4-035d2d178d62', }, isTracked: false, - viewportIdentificator: [], }, ], }, diff --git a/platform/ui/src/components/Svg/getSvg.tsx b/platform/ui/src/components/Svg/getSvg.tsx index dc5e0cb9a..22ebc3b84 100644 --- a/platform/ui/src/components/Svg/getSvg.tsx +++ b/platform/ui/src/components/Svg/getSvg.tsx @@ -1,6 +1,6 @@ import React from 'react'; // Svgs -import logoOhif from './../../assets/svgs/logo-ohif.svg'; +import logoOhif from './../../assets/svgs/ohif-logo.svg'; const SVGS = { 'logo-ohif': logoOhif, diff --git a/platform/ui/src/components/SwitchButton/SwitchButton.tsx b/platform/ui/src/components/SwitchButton/SwitchButton.tsx new file mode 100644 index 000000000..0e6a80483 --- /dev/null +++ b/platform/ui/src/components/SwitchButton/SwitchButton.tsx @@ -0,0 +1,52 @@ +import React, { useCallback, useState } from 'react'; + +import './switchButton.css'; + +export enum SwitchLabelLocation { + left, + right, +} + +export type SwitchButtonProps = { + checked?: boolean; + label?: string; + labelLocation?: SwitchLabelLocation; + onChange?: (checked: boolean) => void; +}; + +const SwitchButton = ({ + label, + checked = false, + onChange, + labelLocation = SwitchLabelLocation.left, +}: SwitchButtonProps) => { + const [isInputChecked, setIsInputChecked] = useState(checked); + + const onHandleChange = useCallback( + event => { + setIsInputChecked(event.target.checked); + onChange?.(event.target.checked); + }, + [onChange] + ); + + // Thanks goes to https://codepen.io/lhermann/pen/EBGZRZ for the inspiration to the code below. + return ( + + ); +}; + +export default SwitchButton; diff --git a/platform/ui/src/components/SwitchButton/__stories__/switchButton.stories.mdx b/platform/ui/src/components/SwitchButton/__stories__/switchButton.stories.mdx new file mode 100644 index 000000000..acbdcc094 --- /dev/null +++ b/platform/ui/src/components/SwitchButton/__stories__/switchButton.stories.mdx @@ -0,0 +1,58 @@ +import SwitchButton, { SwitchLabelLocation } from '../SwitchButton'; + +import { ArgsTable, Story, Canvas, Meta } from '@storybook/addon-docs'; +import { createComponentTemplate } from '../../../storybook/functions/create-component-story'; + +export const argTypes = { + component: SwitchButton, + title: 'Components/SwitchButton', +}; + + + +export const SwitchButtonTemplate = args => ( +
+ +
+); + + + +- [Overview](#overview) +- [Props](#props) +- [Contribute](#contribute) + +## Overview + +A SwitchButton is a checkbox type input/button that can either be on or off (like a light switch). + + + console.info(`${checked ? 'The switch is on.' : 'The switch is off.'}`) + }} +> + + {SwitchButtonTemplate.bind({})} + + + + +## Props + + + +## Usage + +## Contribute + +
diff --git a/platform/ui/src/components/SwitchButton/index.js b/platform/ui/src/components/SwitchButton/index.js new file mode 100644 index 000000000..0f44a7e6e --- /dev/null +++ b/platform/ui/src/components/SwitchButton/index.js @@ -0,0 +1,3 @@ +import SwitchButton, { SwitchLabelLocation } from './SwitchButton'; +export default SwitchButton; +export { SwitchLabelLocation }; diff --git a/platform/ui/src/components/SwitchButton/switchButton.css b/platform/ui/src/components/SwitchButton/switchButton.css new file mode 100644 index 000000000..2eff3baa2 --- /dev/null +++ b/platform/ui/src/components/SwitchButton/switchButton.css @@ -0,0 +1,7 @@ +.switch-button input:checked ~ .switch-button-outer { + @apply border-primary-light; +} +.switch-button input:checked ~ .switch-button-dot { + @apply bg-primary-light; + transform: translateX(12px); +} diff --git a/platform/ui/src/components/ThumbnailList/ThumbnailList.tsx b/platform/ui/src/components/ThumbnailList/ThumbnailList.tsx index dc4bd8322..cf949d202 100644 --- a/platform/ui/src/components/ThumbnailList/ThumbnailList.tsx +++ b/platform/ui/src/components/ThumbnailList/ThumbnailList.tsx @@ -29,7 +29,6 @@ const ThumbnailList = ({ componentType, seriesDate, countIcon, - viewportIdentificator, isTracked, canReject, onReject, @@ -53,7 +52,6 @@ const ThumbnailList = ({ imageSrc={imageSrc} imageAltText={imageAltText} messages={messages} - viewportIdentificator={viewportIdentificator} isActive={isActive} onClick={() => onThumbnailClick(displaySetInstanceUID)} onDoubleClick={() => onThumbnailDoubleClick(displaySetInstanceUID)} @@ -72,7 +70,6 @@ const ThumbnailList = ({ imageSrc={imageSrc} imageAltText={imageAltText} messages={messages} - viewportIdentificator={viewportIdentificator} isTracked={isTracked} isActive={isActive} onClick={() => onThumbnailClick(displaySetInstanceUID)} @@ -96,7 +93,6 @@ const ThumbnailList = ({ onReject={onReject} onClick={() => onThumbnailClick(displaySetInstanceUID)} onDoubleClick={() => onThumbnailDoubleClick(displaySetInstanceUID)} - viewportIdentificator={viewportIdentificator} isHydratedForDerivedDisplaySet={isHydratedForDerivedDisplaySet} /> ); @@ -120,7 +116,6 @@ ThumbnailList.propTypes = { numInstances: PropTypes.number, description: PropTypes.string, componentType: Types.ThumbnailType.isRequired, - viewportIdentificator: Types.StringArray, isTracked: PropTypes.bool, /** * Data the thumbnail should expose to a receiving drop target. Use a matching diff --git a/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx b/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx index 286d723b4..e1bd9acb3 100644 --- a/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx +++ b/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx @@ -24,43 +24,11 @@ function ThumbnailTracked({ onClick, onDoubleClick, onClickUntrack, - viewportIdentificator, isTracked, isActive, }) { const { t } = useTranslation('ThumbnailTracked'); const trackedIcon = isTracked ? 'circled-checkmark' : 'dotted-circle'; - const viewportIdentificatorLabel = viewportIdentificator.join(', '); - const renderViewportLabels = () => { - const MAX_LABELS_PER_COL = 3; - const shouldShowStack = viewportIdentificator.length > MAX_LABELS_PER_COL; - if (shouldShowStack) { - return ( -
-
- {viewportIdentificator.slice(0, MAX_LABELS_PER_COL).map(label => ( -
{label}
- ))} -
- - {`${t('Viewport')}: ${viewportIdentificatorLabel}`} -
- } - > - - -
- ); - } - - return viewportIdentificator.map(label =>
{label}
); - }; return (
- {!!viewportIdentificator.length && ( - {`${t('Viewport')}: ${viewportIdentificatorLabel}`} - )}
} @@ -105,13 +70,6 @@ function ThumbnailTracked({ className="text-primary-light mb-2 w-4" /> - -
- {renderViewportLabels()} -
{isTracked && (
@@ -162,7 +120,6 @@ ThumbnailTracked.propTypes = { onClick: PropTypes.func.isRequired, onDoubleClick: PropTypes.func.isRequired, onClickUntrack: PropTypes.func.isRequired, - viewportIdentificator: PropTypes.array, isTracked: PropTypes.bool, messages: PropTypes.object, isActive: PropTypes.bool.isRequired, diff --git a/platform/ui/src/components/ViewportActionArrows/ViewportActionArrows.tsx b/platform/ui/src/components/ViewportActionArrows/ViewportActionArrows.tsx new file mode 100644 index 000000000..81ed0c564 --- /dev/null +++ b/platform/ui/src/components/ViewportActionArrows/ViewportActionArrows.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import Icon from '../Icon'; +import classNames from 'classnames'; + +const arrowClasses = + 'cursor-pointer flex items-center justify-center shrink-0 text-primary-light active:text-white hover:bg-secondary-light/60 rounded'; + +type ViewportActionArrowsProps = { + onArrowsClick: (direction: number) => void; + className: string; +}; + +function ViewportActionArrows({ onArrowsClick, className }: ViewportActionArrowsProps) { + return ( + // The arrows are only visible when hover over the viewport. +
+
+ onArrowsClick(-1)} + /> +
+
+ onArrowsClick(1)} + /> +
+
+ ); +} + +export default ViewportActionArrows; diff --git a/platform/ui/src/components/ViewportActionArrows/index.tsx b/platform/ui/src/components/ViewportActionArrows/index.tsx new file mode 100644 index 000000000..31f3ce3d7 --- /dev/null +++ b/platform/ui/src/components/ViewportActionArrows/index.tsx @@ -0,0 +1,2 @@ +import ViewportActionArrows from './ViewportActionArrows'; +export default ViewportActionArrows; diff --git a/platform/ui/src/components/ViewportActionCorners/ViewportActionCorners.tsx b/platform/ui/src/components/ViewportActionCorners/ViewportActionCorners.tsx new file mode 100644 index 000000000..78d5dd4dc --- /dev/null +++ b/platform/ui/src/components/ViewportActionCorners/ViewportActionCorners.tsx @@ -0,0 +1,76 @@ +import classNames from 'classnames'; +import React from 'react'; +import { ViewportActionCornersComponentInfo } from '../../types/ViewportActionCornersTypes'; + +export enum ViewportActionCornersLocations { + topLeft, + topRight, + bottomLeft, + bottomRight, +} + +export type ViewportActionCornersProps = { + cornerComponents: Record< + ViewportActionCornersLocations, + Array + >; +}; + +const commonClasses = 'pointer-events-auto flex items-center gap-1'; +const classes = { + [ViewportActionCornersLocations.topLeft]: classNames( + commonClasses, + 'absolute top-[4px] left-[0px] pl-[4px]' + ), + [ViewportActionCornersLocations.topRight]: classNames( + commonClasses, + 'absolute top-[4px] right-[4px] right-viewport-scrollbar' + ), + [ViewportActionCornersLocations.bottomLeft]: classNames( + commonClasses, + 'absolute bottom-[4px] left-[0px] pl-[4px]' + ), + [ViewportActionCornersLocations.bottomRight]: classNames( + commonClasses, + 'absolute bottom-[4px] right-[0px] right-viewport-scrollbar' + ), +}; + +/** + * A component that renders various action items/components to each corner of a viewport. + * The position of each corner's components is such that a single row of components are + * rendered absolutely without intersecting the ViewportOverlay component. + * Note that corner components are passed as an object mapping each corner location + * to an array of components for that location. The components in each array are + * rendered from left to right in the order that they appear in the array. + */ +function ViewportActionCorners({ cornerComponents }: ViewportActionCornersProps) { + if (!cornerComponents) { + return null; + } + + return ( +
{ + event.preventDefault(); + event.stopPropagation(); + }} + > + {Object.entries(cornerComponents).map(([location, locationComponents]) => { + return ( +
+ {locationComponents.map(componentInfo => { + return
{componentInfo.component}
; + })} +
+ ); + })} +
+ ); +} + +export default ViewportActionCorners; diff --git a/platform/ui/src/components/ViewportActionCorners/index.tsx b/platform/ui/src/components/ViewportActionCorners/index.tsx new file mode 100644 index 000000000..9136db97d --- /dev/null +++ b/platform/ui/src/components/ViewportActionCorners/index.tsx @@ -0,0 +1,4 @@ +import ViewportActionCorners, { ViewportActionCornersLocations } from './ViewportActionCorners'; + +export { ViewportActionCornersLocations }; +export default ViewportActionCorners; diff --git a/platform/ui/src/components/ViewportOverlay/ViewportOverlay.css b/platform/ui/src/components/ViewportOverlay/ViewportOverlay.css index fb51cc08e..e8aebd0be 100644 --- a/platform/ui/src/components/ViewportOverlay/ViewportOverlay.css +++ b/platform/ui/src/components/ViewportOverlay/ViewportOverlay.css @@ -10,40 +10,13 @@ text-shadow: 1px 1px #000; pointer-events: none; } -.ViewportOverlay .top-left { - top: 20px; - left: 20px; +.overlay-top { + top: 28px; } -.ViewportOverlay .top-center { - top: 20px; - padding-top: 20px; - width: 100%; - text-align: center; +.overlay-bottom { + bottom: 3px; } -.ViewportOverlay .top-right { - top: 20px; - right: 20px; - text-align: right; -} -.ViewportOverlay .bottom-left { - bottom: 20px; - left: 20px; -} -.ViewportOverlay .bottom-right { - bottom: 20px; - right: 20px; - text-align: right; -} -.ViewportOverlay.controlsVisible .topright, -.ViewportOverlay.controlsVisible .bottomright { - right: calc(20px + 19px); -} -.ViewportOverlay svg { - color: #9ccef9; - fill: #9ccef9; - stroke: #9ccef9; - background-color: transparent; - margin: 2px; - width: 18px; - height: 18px; + +.overlay-text { + text-shadow: 0.8px 0.8px 0.5px rgba(0, 0, 0, 0.75); } diff --git a/platform/ui/src/components/ViewportOverlay/ViewportOverlay.tsx b/platform/ui/src/components/ViewportOverlay/ViewportOverlay.tsx index e99a3d204..971b2227f 100644 --- a/platform/ui/src/components/ViewportOverlay/ViewportOverlay.tsx +++ b/platform/ui/src/components/ViewportOverlay/ViewportOverlay.tsx @@ -3,11 +3,16 @@ import classnames from 'classnames'; import './ViewportOverlay.css'; +// The overlay-top and overlay-bottom classes are explicitly needed to offset +// the overlays (i.e. via absolute positioning) such the ViewportActionCorners +// have space for its child components. +// ToDo: offset the ViewportOverlay automatically via css to account for the +// space needed for ViewportActionCorners. const classes = { - topLeft: 'top-viewport left-viewport', - topRight: 'top-viewport right-viewport-scrollbar', - bottomRight: 'bottom-viewport right-viewport-scrollbar', - bottomLeft: 'bottom-viewport left-viewport', + topLeft: 'overlay-top left-viewport', + topRight: 'overlay-top right-viewport-scrollbar', + bottomRight: 'overlay-bottom right-viewport-scrollbar', + bottomLeft: 'overlay-bottom left-viewport', }; export type ViewportOverlayProps = { @@ -27,7 +32,14 @@ const ViewportOverlay = ({ }: ViewportOverlayProps) => { const overlay = 'absolute pointer-events-none viewport-overlay'; return ( -
+
{topRight}
{bottomRight}
diff --git a/platform/ui/src/components/ViewportPane/ViewportPane.tsx b/platform/ui/src/components/ViewportPane/ViewportPane.tsx index 5aa06ffb3..ada09c871 100644 --- a/platform/ui/src/components/ViewportPane/ViewportPane.tsx +++ b/platform/ui/src/components/ViewportPane/ViewportPane.tsx @@ -64,7 +64,7 @@ function ViewportPane({ onScroll={onInteractionHandler} onWheel={onInteractionHandler} className={classnames( - 'hover:border-primary-light group h-full w-full overflow-hidden rounded-md transition duration-300', + 'group h-full w-full overflow-hidden rounded-md transition duration-300', { 'border-primary-light border-2': isActive, 'border-2 border-transparent': !isActive, @@ -77,10 +77,10 @@ function ViewportPane({ >
{ closeButton: true, title: null, customClassName: '', + movable: false, + containerDimensions: null, + contentDimensions: null, }; const { t } = useTranslation('Modals'); @@ -73,6 +76,9 @@ const ModalProvider = ({ children, modal: Modal, service }) => { shouldCloseOnEsc, closeButton, shouldCloseOnOverlayClick, + movable, + containerDimensions, + contentDimensions, } = options; return ( @@ -86,6 +92,9 @@ const ModalProvider = ({ children, modal: Modal, service }) => { closeButton={closeButton} onClose={hide} shouldCloseOnOverlayClick={shouldCloseOnOverlayClick} + movable={movable} + containerDimensions={containerDimensions} + contentDimensions={contentDimensions} > =16": - version "18.2.70" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.70.tgz#89a37f9e0a6a4931f4259c598f40fd44dd6abf71" - integrity sha512-hjlM2hho2vqklPhopNkXkdkeq6Lv8WSZTpr7956zY+3WS5cfYUewtCzsJLsbW5dEv3lfSeQ4W14ZFeKC437JRQ== + version "18.2.73" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.73.tgz#0579548ad122660d99e00499d22e33b81e73ed94" + integrity sha512-XcGdod0Jjv84HOC7N5ziY3x+qL0AfmubvKOZ9hJjJ2yd5EE+KYjWhdOjt387e9HPheHkdggF9atTifMRtyAaRA== dependencies: "@types/prop-types" "*" - "@types/scheduler" "*" csstype "^3.0.2" "@types/react@^17.0.38": - version "17.0.79" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.79.tgz#67693ab9bc476780d968326658619fa7f25b8935" - integrity sha512-gavKA8AwJAML9zWHuiQRASjrrPJHbT/zrUDHiUGUf+l5a3pkEd6atvjjq+8y2vfRHBJLQJjFpxSa9I8qe9zHAw== + version "17.0.80" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.80.tgz#a5dfc351d6a41257eb592d73d3a85d3b7dbcbb41" + integrity sha512-LrgHIu2lEtIo8M7d1FcI3BdwXWoRQwMoXOZ7+dPTW0lYREjmlHl3P0U1VD0i/9tppOuv8/sam7sOjx34TxSFbA== dependencies: "@types/prop-types" "*" - "@types/scheduler" "*" + "@types/scheduler" "^0.16" csstype "^3.0.2" "@types/resolve@1.17.1": @@ -5462,7 +5478,7 @@ dependencies: "@types/node" "*" -"@types/scheduler@*": +"@types/scheduler@^0.16": version "0.16.8" resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff" integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A== @@ -6118,24 +6134,25 @@ algoliasearch-helper@^3.10.0: "@algolia/events" "^4.0.1" algoliasearch@^4.13.1, algoliasearch@^4.19.1: - version "4.22.1" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.22.1.tgz#f10fbecdc7654639ec20d62f109c1b3a46bc6afc" - integrity sha512-jwydKFQJKIx9kIZ8Jm44SdpigFwRGPESaxZBaHSV0XWN2yBJAOT4mT7ppvlrpA4UGzz92pqFnVKr/kaZXrcreg== + version "4.23.2" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.23.2.tgz#3b7bc93d98f3965628c73a06cbf9203531324a9d" + integrity sha512-8aCl055IsokLuPU8BzLjwzXjb7ty9TPcUFFOk0pYOwsE5DMVhE3kwCMFtsCFKcnoPZK7oObm+H5mbnSO/9ioxQ== dependencies: - "@algolia/cache-browser-local-storage" "4.22.1" - "@algolia/cache-common" "4.22.1" - "@algolia/cache-in-memory" "4.22.1" - "@algolia/client-account" "4.22.1" - "@algolia/client-analytics" "4.22.1" - "@algolia/client-common" "4.22.1" - "@algolia/client-personalization" "4.22.1" - "@algolia/client-search" "4.22.1" - "@algolia/logger-common" "4.22.1" - "@algolia/logger-console" "4.22.1" - "@algolia/requester-browser-xhr" "4.22.1" - "@algolia/requester-common" "4.22.1" - "@algolia/requester-node-http" "4.22.1" - "@algolia/transporter" "4.22.1" + "@algolia/cache-browser-local-storage" "4.23.2" + "@algolia/cache-common" "4.23.2" + "@algolia/cache-in-memory" "4.23.2" + "@algolia/client-account" "4.23.2" + "@algolia/client-analytics" "4.23.2" + "@algolia/client-common" "4.23.2" + "@algolia/client-personalization" "4.23.2" + "@algolia/client-search" "4.23.2" + "@algolia/logger-common" "4.23.2" + "@algolia/logger-console" "4.23.2" + "@algolia/recommend" "4.23.2" + "@algolia/requester-browser-xhr" "4.23.2" + "@algolia/requester-common" "4.23.2" + "@algolia/requester-node-http" "4.23.2" + "@algolia/transporter" "4.23.2" ansi-align@^3.0.0, ansi-align@^3.0.1: version "3.0.1" @@ -9371,9 +9388,9 @@ ejs@^3.1.6, ejs@^3.1.7, ejs@^3.1.8: jake "^10.8.5" electron-to-chromium@^1.4.668: - version "1.4.715" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.715.tgz#bb16bcf2a3537962fccfa746b5c98c5f7404ff46" - integrity sha512-XzWNH4ZSa9BwVUQSDorPWAUQ5WGuYz7zJUNpNif40zFCiCl20t8zgylmreNmn26h5kiyw2lg7RfTmeMBsDklqg== + version "1.4.721" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.721.tgz#a9ee55ba7e54d9ecbcc19825116f3752e7d60ef2" + integrity sha512-k1x2r6foI8iJOp+1qTxbbrrWMsOiHkzGBYwYigaq+apO1FSqtn44KTo3Sy69qt7CRr7149zTcsDvH7MUKsOuIQ== elegant-spinner@^1.0.1: version "1.0.1" @@ -9603,9 +9620,9 @@ es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.17: safe-array-concat "^1.1.2" es-module-lexer@^1.2.1, es-module-lexer@^1.4.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.2.tgz#ba1a62255ff9b41023aaf9bd08c016a5f1a3fef3" - integrity sha512-7nOqkomXZEaxUDJw21XZNtRk739QvrPSoZoRtbsEfcii00vdzZUh6zh1CQwHhrib8MdEtJfv5rJiGeb4KuV/vw== + version "1.5.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.0.tgz#4878fee3789ad99e065f975fdd3c645529ff0236" + integrity sha512-pqrTKmwEIgafsYZAGw9kszYzmagcE/n4dbgwGWLEXg7J4QFJVQRBld8j3Q3GNez79jzxZshq0bcT962QHOghjw== es-object-atoms@^1.0.0: version "1.0.0" @@ -10755,9 +10772,9 @@ flatted@^3.2.9: integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== flow-parser@0.*: - version "0.231.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.231.0.tgz#13daa172b3c06ffacbb31025592dc0db41fe28f3" - integrity sha512-WVzuqwq7ZnvBceCG0DGeTQebZE+iIU0mlk5PmJgYj9DDrt+0isGC2m1ezW9vxL4V+HERJJo9ExppOnwKH2op6Q== + version "0.232.0" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.232.0.tgz#db93a660e7017bd366290944c3328ca506ca7d2b" + integrity sha512-U8vcKyYdM+Kb0tPzfPJ5JyPMU0uXKwHxp0L6BcEc+wBlbTW9qRhOqV5DeGXclgclVvtqQNGEG8Strj/b6c/IxA== flux@^4.0.1: version "4.0.4" @@ -11227,15 +11244,15 @@ glob@7.1.4: path-is-absolute "^1.0.0" glob@^10.0.0, glob@^10.2.2: - version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== + version "10.3.12" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.12.tgz#3a65c363c2e9998d220338e88a5f6ac97302960b" + integrity sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg== dependencies: foreground-child "^3.1.0" - jackspeak "^2.3.5" + jackspeak "^2.3.6" minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" + minipass "^7.0.4" + path-scurry "^1.10.2" glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.3" @@ -12814,7 +12831,7 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" -jackspeak@^2.3.5: +jackspeak@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== @@ -14079,6 +14096,11 @@ lowercase-keys@^3.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== +lru-cache@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" + integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== + lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -14106,11 +14128,6 @@ lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== -"lru-cache@^9.1.1 || ^10.0.0": - version "10.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" - integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== - magic-string@^0.25.0, magic-string@^0.25.1, magic-string@^0.25.2, magic-string@^0.25.7: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -14875,7 +14892,7 @@ minimatch@3.1.2, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch dependencies: brace-expansion "^1.1.7" -minimatch@9.0.3, minimatch@^9.0.0, minimatch@^9.0.1: +minimatch@9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== @@ -14896,6 +14913,13 @@ minimatch@^8.0.2: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.0, minimatch@^9.0.1: + version "9.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" + integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== + dependencies: + brace-expansion "^2.0.1" + minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -14985,7 +15009,7 @@ minipass@^5.0.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.3: +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.3, minipass@^7.0.4: version "7.0.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== @@ -16214,12 +16238,12 @@ path-root@^0.1.1: dependencies: path-root-regex "^0.1.0" -path-scurry@^1.10.1, path-scurry@^1.6.1: - version "1.10.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" - integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== +path-scurry@^1.10.2, path-scurry@^1.6.1: + version "1.10.2" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.2.tgz#8f6357eb1239d5fa1da8b9f70e9c080675458ba7" + integrity sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA== dependencies: - lru-cache "^9.1.1 || ^10.0.0" + lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-to-regexp@0.1.7: @@ -17034,9 +17058,9 @@ prettier-linter-helpers@^1.0.0: fast-diff "^1.1.2" prettier-plugin-tailwindcss@^0.5.4: - version "0.5.12" - resolved "https://registry.yarnpkg.com/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.12.tgz#655999849344548ecf4d9b47a051ed856f041c72" - integrity sha512-o74kiDBVE73oHW+pdkFSluHBL3cYEvru5YgEqNkBMFF7Cjv+w1vI565lTlfoJT4VLWDe0FMtZ7FkE/7a4pMXSQ== + version "0.5.13" + resolved "https://registry.yarnpkg.com/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.13.tgz#ee3c1e07848c90abdd1edde36a09366327e31e26" + integrity sha512-2tPWHCFNC+WRjAC4SIWQNSOdcL1NNkydXim8w7TDqlZi+/ulZYz2OouAI6qMtkggnPt7lGamboj6LcTMwcCvoQ== prettier@^2.8.0: version "2.8.8" @@ -19889,9 +19913,9 @@ table@^5.2.3: string-width "^3.0.0" table@^6.0.9: - version "6.8.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" - integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== + version "6.8.2" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.2.tgz#c5504ccf201213fa227248bdc8c5569716ac6c58" + integrity sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA== dependencies: ajv "^8.0.1" lodash.truncate "^4.4.2" @@ -20060,9 +20084,9 @@ terser-webpack-plugin@^5.1.1, terser-webpack-plugin@^5.1.4, terser-webpack-plugi terser "^5.26.0" terser@^5.0.0, terser@^5.10.0, terser@^5.26.0: - version "5.29.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.29.2.tgz#c17d573ce1da1b30f21a877bffd5655dd86fdb35" - integrity sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw== + version "5.30.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.30.0.tgz#64cb2af71e16ea3d32153f84d990f9be0cdc22bf" + integrity sha512-Y/SblUl5kEyEFzhMAQdsxVHh+utAxd4IuRNJzKywY/4uzSogh3G219jqbDDxYu4MXO9CzY3tSEqmZvW6AoEDJw== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -20689,9 +20713,9 @@ unpipe@1.0.0, unpipe@~1.0.0: integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== unplugin@^1.3.1: - version "1.10.0" - resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.10.0.tgz#9cb8140f61e3fbcf27c7c38d305e9d62d5dbbf0b" - integrity sha512-CuZtvvO8ua2Wl+9q2jEaqH6m3DoQ38N7pvBYQbbaeNlWGvK2l6GHiKi29aIHDPoSxdUzQ7Unevf1/ugil5X6Pg== + version "1.10.1" + resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.10.1.tgz#8ceda065dc71bc67d923dea0920f05c67f2cd68c" + integrity sha512-d6Mhq8RJeGA8UfKCu54Um4lFA0eSaRa3XxdAJg8tIdxbu1ubW0hBCZUL7yI2uGyYCRndvbK8FLHzqy2XKfeMsg== dependencies: acorn "^8.11.3" chokidar "^3.6.0" @@ -21179,9 +21203,9 @@ webpack-dev-middleware@^5.3.0, webpack-dev-middleware@^5.3.4: schema-utils "^4.0.0" webpack-dev-middleware@^6.1.1: - version "6.1.2" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-6.1.2.tgz#0463232e59b7d7330fa154121528d484d36eb973" - integrity sha512-Wu+EHmX326YPYUpQLKmKbTyZZJIB8/n6R09pTmB03kJmnMsVPTo9COzHZFr01txwaCAuZvfBJE4ZCHRcKs5JaQ== + version "6.1.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz#79f4103f8c898564c9e96c3a9c2422de50f249bc" + integrity sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw== dependencies: colorette "^2.0.10" memfs "^3.4.12"