chore(prettier): full repo linting and code reformatting once and for all (#3627)
This commit is contained in:
1 parent
01500a2d4c
commit
9045ddaedc
656 files changed
+21737
-20628
No files matched your search
@@ -40,13 +40,7 @@ module.exports = (env, argv) => {
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
},
|
||||
externals: [
|
||||
/\b(vtk.js)/,
|
||||
/\b(dcmjs)/,
|
||||
/\b(gl-matrix)/,
|
||||
/^@ohif/,
|
||||
/^@cornerstonejs/,
|
||||
],
|
||||
externals: [/\b(vtk.js)/, /\b(dcmjs)/, /\b(gl-matrix)/, /^@ohif/, /^@cornerstonejs/],
|
||||
plugins: [
|
||||
new webpack.optimize.LimitChunkCountPlugin({
|
||||
maxChunks: 1,
|
||||
|
||||
@@ -11,10 +11,7 @@ import {
|
||||
} from '@cornerstonejs/core';
|
||||
import { MeasurementService } from '@ohif/core';
|
||||
import { Notification, useViewportDialog } from '@ohif/ui';
|
||||
import {
|
||||
IStackViewport,
|
||||
IVolumeViewport,
|
||||
} from '@cornerstonejs/core/dist/esm/types';
|
||||
import { IStackViewport, IVolumeViewport } from '@cornerstonejs/core/dist/esm/types';
|
||||
|
||||
import { setEnabledElement } from '../state';
|
||||
|
||||
@@ -42,24 +39,15 @@ function areEqual(prevProps, nextProps) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
prevProps.viewportOptions.orientation !==
|
||||
nextProps.viewportOptions.orientation
|
||||
) {
|
||||
if (prevProps.viewportOptions.orientation !== nextProps.viewportOptions.orientation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
prevProps.viewportOptions.toolGroupId !==
|
||||
nextProps.viewportOptions.toolGroupId
|
||||
) {
|
||||
if (prevProps.viewportOptions.toolGroupId !== nextProps.viewportOptions.toolGroupId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
prevProps.viewportOptions.viewportType !==
|
||||
nextProps.viewportOptions.viewportType
|
||||
) {
|
||||
if (prevProps.viewportOptions.viewportType !== nextProps.viewportOptions.viewportType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -79,8 +67,7 @@ function areEqual(prevProps, nextProps) {
|
||||
|
||||
const foundDisplaySet = nextDisplaySets.find(
|
||||
nextDisplaySet =>
|
||||
nextDisplaySet.displaySetInstanceUID ===
|
||||
prevDisplaySet.displaySetInstanceUID
|
||||
nextDisplaySet.displaySetInstanceUID === prevDisplaySet.displaySetInstanceUID
|
||||
);
|
||||
|
||||
if (!foundDisplaySet) {
|
||||
@@ -95,9 +82,7 @@ function areEqual(prevProps, nextProps) {
|
||||
// check if their imageIds are the same
|
||||
if (foundDisplaySet.images?.length) {
|
||||
for (let j = 0; j < foundDisplaySet.images.length; j++) {
|
||||
if (
|
||||
foundDisplaySet.images[j].imageId !== prevDisplaySet.images[j].imageId
|
||||
) {
|
||||
if (foundDisplaySet.images[j].imageId !== prevDisplaySet.images[j].imageId) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -163,16 +148,9 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
const renderingEngineId = viewportInfo.getRenderingEngineId();
|
||||
const syncGroups = viewportInfo.getSyncGroups();
|
||||
|
||||
toolGroupService.removeViewportFromToolGroup(
|
||||
viewportId,
|
||||
renderingEngineId
|
||||
);
|
||||
toolGroupService.removeViewportFromToolGroup(viewportId, renderingEngineId);
|
||||
|
||||
syncGroupService.removeViewportFromSyncGroup(
|
||||
viewportId,
|
||||
renderingEngineId,
|
||||
syncGroups
|
||||
);
|
||||
syncGroupService.removeViewportFromSyncGroup(viewportId, renderingEngineId, syncGroups);
|
||||
},
|
||||
[viewportId]
|
||||
);
|
||||
@@ -185,9 +163,7 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
}
|
||||
|
||||
const { viewportId, element } = evt.detail;
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfo(
|
||||
viewportId
|
||||
);
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
|
||||
setEnabledElement(viewportId, element);
|
||||
setEnabledVPElement(element);
|
||||
|
||||
@@ -195,17 +171,9 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
const toolGroupId = viewportInfo.getToolGroupId();
|
||||
const syncGroups = viewportInfo.getSyncGroups();
|
||||
|
||||
toolGroupService.addViewportToToolGroup(
|
||||
viewportId,
|
||||
renderingEngineId,
|
||||
toolGroupId
|
||||
);
|
||||
toolGroupService.addViewportToToolGroup(viewportId, renderingEngineId, toolGroupId);
|
||||
|
||||
syncGroupService.addViewportToSyncGroup(
|
||||
viewportId,
|
||||
renderingEngineId,
|
||||
syncGroups
|
||||
);
|
||||
syncGroupService.addViewportToSyncGroup(viewportId, renderingEngineId, syncGroups);
|
||||
|
||||
if (onElementEnabled) {
|
||||
onElementEnabled(evt);
|
||||
@@ -218,17 +186,12 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
useEffect(() => {
|
||||
cornerstoneViewportService.enableViewport(viewportId, elementRef.current);
|
||||
|
||||
eventTarget.addEventListener(
|
||||
Enums.Events.ELEMENT_ENABLED,
|
||||
elementEnabledHandler
|
||||
);
|
||||
eventTarget.addEventListener(Enums.Events.ELEMENT_ENABLED, elementEnabledHandler);
|
||||
|
||||
setImageScrollBarHeight();
|
||||
|
||||
return () => {
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfo(
|
||||
viewportId
|
||||
);
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
|
||||
|
||||
if (!viewportInfo) {
|
||||
return;
|
||||
@@ -241,10 +204,7 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
onElementDisabled(viewportInfo);
|
||||
}
|
||||
|
||||
eventTarget.removeEventListener(
|
||||
Enums.Events.ELEMENT_ENABLED,
|
||||
elementEnabledHandler
|
||||
);
|
||||
eventTarget.removeEventListener(Enums.Events.ELEMENT_ENABLED, elementEnabledHandler);
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -267,9 +227,7 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
return;
|
||||
}
|
||||
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfo(
|
||||
viewportId
|
||||
);
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
|
||||
|
||||
if (viewportInfo.hasDisplaySet(invalidatedDisplaySetInstanceUID)) {
|
||||
const viewportData = viewportInfo.getViewportData();
|
||||
@@ -281,11 +239,7 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
);
|
||||
|
||||
const keepCamera = true;
|
||||
cornerstoneViewportService.updateViewport(
|
||||
viewportId,
|
||||
newViewportData,
|
||||
keepCamera
|
||||
);
|
||||
cornerstoneViewportService.updateViewport(viewportId, newViewportData, keepCamera);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -311,16 +265,11 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
// The presentation state will have been stored previously by closing
|
||||
// a viewport. Otherwise, this viewport will be unchanged and the
|
||||
// presentation information will be directly carried over.
|
||||
const {
|
||||
lutPresentationStore,
|
||||
positionPresentationStore,
|
||||
} = stateSyncService.getState();
|
||||
const { lutPresentationStore, positionPresentationStore } = stateSyncService.getState();
|
||||
const { presentationIds } = viewportOptions;
|
||||
const presentations = {
|
||||
positionPresentation:
|
||||
positionPresentationStore[presentationIds?.positionPresentationId],
|
||||
lutPresentation:
|
||||
lutPresentationStore[presentationIds?.lutPresentationId],
|
||||
positionPresentation: positionPresentationStore[presentationIds?.positionPresentationId],
|
||||
lutPresentation: lutPresentationStore[presentationIds?.lutPresentationId],
|
||||
};
|
||||
let measurement;
|
||||
if (cacheJumpToMeasurementEvent?.viewportId === viewportId) {
|
||||
@@ -459,11 +408,12 @@ function _subscribeToJumpToMeasurementEvents(
|
||||
}
|
||||
if (cacheJumpToMeasurementEvent.cornerstoneViewport === undefined) {
|
||||
// Decide on which viewport should handle this
|
||||
cacheJumpToMeasurementEvent.cornerstoneViewport = cornerstoneViewportService.getViewportIdToJump(
|
||||
jumpId,
|
||||
measurement.displaySetInstanceUID,
|
||||
{ referencedImageId: measurement.referencedImageId }
|
||||
);
|
||||
cacheJumpToMeasurementEvent.cornerstoneViewport =
|
||||
cornerstoneViewportService.getViewportIdToJump(
|
||||
jumpId,
|
||||
measurement.displaySetInstanceUID,
|
||||
{ referencedImageId: measurement.referencedImageId }
|
||||
);
|
||||
}
|
||||
if (cacheJumpToMeasurementEvent.cornerstoneViewport !== viewportId) {
|
||||
return;
|
||||
@@ -500,9 +450,7 @@ function _checkForCachedJumpToMeasurementEvents(
|
||||
cacheJumpToMeasurementEvent = null;
|
||||
return;
|
||||
}
|
||||
const displaysUIDs = displaySets.map(
|
||||
displaySet => displaySet.displaySetInstanceUID
|
||||
);
|
||||
const displaysUIDs = displaySets.map(displaySet => displaySet.displaySetInstanceUID);
|
||||
if (!displaysUIDs?.length) {
|
||||
return;
|
||||
}
|
||||
@@ -541,9 +489,7 @@ function _jumpToMeasurement(
|
||||
return;
|
||||
}
|
||||
|
||||
const referencedDisplaySet = displaySetService.getDisplaySetByUID(
|
||||
displaySetInstanceUID
|
||||
);
|
||||
const referencedDisplaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||
|
||||
// Todo: setCornerstoneMeasurementActive should be handled by the toolGroupManager
|
||||
// to set it properly
|
||||
@@ -555,9 +501,7 @@ function _jumpToMeasurement(
|
||||
|
||||
if (enabledElement) {
|
||||
// See how the jumpToSlice() of Cornerstone3D deals with imageIdx param.
|
||||
const viewport = enabledElement.viewport as
|
||||
| IStackViewport
|
||||
| IVolumeViewport;
|
||||
const viewport = enabledElement.viewport as IStackViewport | IVolumeViewport;
|
||||
|
||||
let imageIdIndex = 0;
|
||||
let viewportCameraDirectionMatch = true;
|
||||
@@ -565,14 +509,9 @@ function _jumpToMeasurement(
|
||||
if (viewport instanceof StackViewport) {
|
||||
const imageIds = viewport.getImageIds();
|
||||
imageIdIndex = imageIds.findIndex(imageId => {
|
||||
const {
|
||||
SOPInstanceUID: aSOPInstanceUID,
|
||||
frameNumber: aFrameNumber,
|
||||
} = getSOPInstanceAttributes(imageId);
|
||||
return (
|
||||
aSOPInstanceUID === SOPInstanceUID &&
|
||||
(!frameNumber || frameNumber === aFrameNumber)
|
||||
);
|
||||
const { SOPInstanceUID: aSOPInstanceUID, frameNumber: aFrameNumber } =
|
||||
getSOPInstanceAttributes(imageId);
|
||||
return aSOPInstanceUID === SOPInstanceUID && (!frameNumber || frameNumber === aFrameNumber);
|
||||
});
|
||||
} else {
|
||||
// for volume viewport we can't rely on the imageIdIndex since it can be
|
||||
@@ -587,10 +526,7 @@ function _jumpToMeasurement(
|
||||
// should compare abs for both planes since the direction can be flipped
|
||||
if (
|
||||
measurementViewPlane &&
|
||||
!csUtils.isEqual(
|
||||
measurementViewPlane.map(Math.abs),
|
||||
viewportViewPlane.map(Math.abs)
|
||||
)
|
||||
!csUtils.isEqual(measurementViewPlane.map(Math.abs), viewportViewPlane.map(Math.abs))
|
||||
) {
|
||||
viewportCameraDirectionMatch = false;
|
||||
}
|
||||
@@ -629,10 +565,7 @@ OHIFCornerstoneViewport.propTypes = {
|
||||
// Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation
|
||||
// of the imageData in the OHIFCornerstoneViewport. This prop is used
|
||||
// to set the initial state of the viewport's first image to render
|
||||
initialImageIdOrIndex: PropTypes.oneOfType([
|
||||
PropTypes.string,
|
||||
PropTypes.number,
|
||||
]),
|
||||
initialImageIdOrIndex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
};
|
||||
|
||||
export default OHIFCornerstoneViewport;
|
||||
@@ -3,12 +3,7 @@ import { vec3 } from 'gl-matrix';
|
||||
import PropTypes from 'prop-types';
|
||||
import { metaData, Enums, utilities } from '@cornerstonejs/core';
|
||||
import { ViewportOverlay } from '@ohif/ui';
|
||||
import {
|
||||
formatPN,
|
||||
formatDICOMDate,
|
||||
formatDICOMTime,
|
||||
formatNumberPrecision,
|
||||
} from './utils';
|
||||
import { formatPN, formatDICOMDate, formatDICOMTime, formatNumberPrecision } from './utils';
|
||||
import { InstanceMetadata } from 'platform/core/src/types';
|
||||
import { ServicesManager } from '@ohif/core';
|
||||
import { ImageSliceData } from '@cornerstonejs/core/dist/esm/types';
|
||||
@@ -55,13 +50,9 @@ function VOIOverlayItem({ voi, customization }: OverlayItemProps) {
|
||||
style={{ color: (customization && customization.color) || undefined }}
|
||||
>
|
||||
<span className="mr-1 shrink-0">W:</span>
|
||||
<span className="ml-1 mr-2 font-light shrink-0">
|
||||
{windowWidth.toFixed(0)}
|
||||
</span>
|
||||
<span className="ml-1 mr-2 shrink-0 font-light">{windowWidth.toFixed(0)}</span>
|
||||
<span className="mr-1 shrink-0">L:</span>
|
||||
<span className="ml-1 font-light shrink-0">
|
||||
{windowCenter.toFixed(0)}
|
||||
</span>
|
||||
<span className="ml-1 shrink-0 font-light">{windowCenter.toFixed(0)}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -116,11 +107,8 @@ function CustomizableViewportOverlay({
|
||||
viewportId,
|
||||
servicesManager,
|
||||
}) {
|
||||
const {
|
||||
toolbarService,
|
||||
cornerstoneViewportService,
|
||||
customizationService,
|
||||
} = servicesManager.services;
|
||||
const { toolbarService, cornerstoneViewportService, customizationService } =
|
||||
servicesManager.services;
|
||||
const [voi, setVOI] = useState({ windowCenter: null, windowWidth: null });
|
||||
const [scale, setScale] = useState(1);
|
||||
const [activeTools, setActiveTools] = useState([]);
|
||||
@@ -149,12 +137,7 @@ function CustomizableViewportOverlay({
|
||||
|
||||
const instanceNumber = useMemo(() => {
|
||||
if (viewportData != null) {
|
||||
return _getInstanceNumber(
|
||||
viewportData,
|
||||
viewportId,
|
||||
imageIndex,
|
||||
cornerstoneViewportService
|
||||
);
|
||||
return _getInstanceNumber(viewportData, viewportId, imageIndex, cornerstoneViewportService);
|
||||
}
|
||||
return null;
|
||||
}, [viewportData, viewportId, imageIndex, cornerstoneViewportService]);
|
||||
@@ -178,10 +161,7 @@ function CustomizableViewportOverlay({
|
||||
}
|
||||
|
||||
const { lower, upper } = range;
|
||||
const { windowWidth, windowCenter } = utilities.windowLevel.toWindowLevel(
|
||||
lower,
|
||||
upper
|
||||
);
|
||||
const { windowWidth, windowCenter } = utilities.windowLevel.toWindowLevel(lower, upper);
|
||||
|
||||
setVOI({ windowCenter, windowWidth });
|
||||
};
|
||||
@@ -204,9 +184,7 @@ function CustomizableViewportOverlay({
|
||||
previousCamera.parallelScale !== camera.parallelScale ||
|
||||
previousCamera.scale !== camera.scale
|
||||
) {
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(
|
||||
viewportId
|
||||
);
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
|
||||
if (!viewport) {
|
||||
return;
|
||||
@@ -225,8 +203,7 @@ function CustomizableViewportOverlay({
|
||||
|
||||
const { spacing } = imageData;
|
||||
// convert parallel scale to scale
|
||||
const scale =
|
||||
(element.clientHeight * spacing[0] * 0.5) / camera.parallelScale;
|
||||
const scale = (element.clientHeight * spacing[0] * 0.5) / camera.parallelScale;
|
||||
setScale(scale);
|
||||
}
|
||||
};
|
||||
@@ -342,9 +319,7 @@ function CustomizableViewportOverlay({
|
||||
return (
|
||||
<>
|
||||
{items.map((item, i) => (
|
||||
<div key={`bottomLeftOverlayItem_${i}`}>
|
||||
{_renderOverlayItem(item)}
|
||||
</div>
|
||||
<div key={`bottomLeftOverlayItem_${i}`}>{_renderOverlayItem(item)}</div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
@@ -355,9 +330,7 @@ function CustomizableViewportOverlay({
|
||||
return (
|
||||
<>
|
||||
{items.map((item, i) => (
|
||||
<div key={`bottomRightOverlayItem_${i}`}>
|
||||
{_renderOverlayItem(item)}
|
||||
</div>
|
||||
<div key={`bottomRightOverlayItem_${i}`}>{_renderOverlayItem(item)}</div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
@@ -387,12 +360,7 @@ function _getViewportInstance(viewportData, imageIndex) {
|
||||
return imageId ? metaData.get('instance', imageId) || {} : {};
|
||||
}
|
||||
|
||||
function _getInstanceNumber(
|
||||
viewportData,
|
||||
viewportId,
|
||||
imageIndex,
|
||||
cornerstoneViewportService
|
||||
) {
|
||||
function _getInstanceNumber(viewportData, viewportId, imageIndex, cornerstoneViewportService) {
|
||||
let instanceNumber;
|
||||
|
||||
if (viewportData.viewportType === Enums.ViewportType.STACK) {
|
||||
@@ -435,11 +403,7 @@ function _getInstanceNumberFromStack(viewportData, imageIndex) {
|
||||
// Since volume viewports can be in any view direction, they can render
|
||||
// a reconstructed image which don't have imageIds; therefore, no instance and instanceNumber
|
||||
// Here we check if viewport is in the acquisition direction and if so, we get the instanceNumber
|
||||
function _getInstanceNumberFromVolume(
|
||||
viewportData,
|
||||
viewportId,
|
||||
cornerstoneViewportService
|
||||
) {
|
||||
function _getInstanceNumberFromVolume(viewportData, viewportId, cornerstoneViewportService) {
|
||||
const volumes = viewportData.volumes;
|
||||
|
||||
// Todo: support fusion of acquisition plane which has instanceNumber
|
||||
@@ -450,9 +414,7 @@ function _getInstanceNumberFromVolume(
|
||||
const volume = volumes[0];
|
||||
const { direction, imageIds } = volume;
|
||||
|
||||
const cornerstoneViewport = cornerstoneViewportService.getCornerstoneViewport(
|
||||
viewportId
|
||||
);
|
||||
const cornerstoneViewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
|
||||
if (!cornerstoneViewport) {
|
||||
return;
|
||||
@@ -475,8 +437,7 @@ function _getInstanceNumberFromVolume(
|
||||
return {};
|
||||
}
|
||||
|
||||
const { instanceNumber } =
|
||||
metaData.get('generalImageModule', imageId) || {};
|
||||
const { instanceNumber } = metaData.get('generalImageModule', imageId) || {};
|
||||
return parseInt(instanceNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,10 @@ function CornerstoneImageScrollbar({
|
||||
scrollbarHeight,
|
||||
servicesManager,
|
||||
}) {
|
||||
const {
|
||||
cineService,
|
||||
cornerstoneViewportService,
|
||||
} = (servicesManager as ServicesManger).services;
|
||||
const { cineService, cornerstoneViewportService } = (servicesManager as ServicesManger).services;
|
||||
|
||||
const onImageScrollbarChange = (imageIndex, viewportId) => {
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(
|
||||
viewportId
|
||||
);
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
|
||||
const { isCineEnabled } = cineService.getState();
|
||||
|
||||
@@ -43,9 +38,7 @@ function CornerstoneImageScrollbar({
|
||||
return;
|
||||
}
|
||||
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(
|
||||
viewportId
|
||||
);
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
|
||||
if (!viewport) {
|
||||
return;
|
||||
@@ -90,16 +83,10 @@ function CornerstoneImageScrollbar({
|
||||
});
|
||||
};
|
||||
|
||||
element.addEventListener(
|
||||
Enums.Events.STACK_VIEWPORT_SCROLL,
|
||||
updateStackIndex
|
||||
);
|
||||
element.addEventListener(Enums.Events.STACK_VIEWPORT_SCROLL, updateStackIndex);
|
||||
|
||||
return () => {
|
||||
element.removeEventListener(
|
||||
Enums.Events.STACK_VIEWPORT_SCROLL,
|
||||
updateStackIndex
|
||||
);
|
||||
element.removeEventListener(Enums.Events.STACK_VIEWPORT_SCROLL, updateStackIndex);
|
||||
};
|
||||
}, [viewportData, element]);
|
||||
|
||||
@@ -117,19 +104,14 @@ function CornerstoneImageScrollbar({
|
||||
element.addEventListener(Enums.Events.VOLUME_NEW_IMAGE, updateVolumeIndex);
|
||||
|
||||
return () => {
|
||||
element.removeEventListener(
|
||||
Enums.Events.VOLUME_NEW_IMAGE,
|
||||
updateVolumeIndex
|
||||
);
|
||||
element.removeEventListener(Enums.Events.VOLUME_NEW_IMAGE, updateVolumeIndex);
|
||||
};
|
||||
}, [viewportData, element]);
|
||||
|
||||
return (
|
||||
<ImageScrollbar
|
||||
onChange={evt => onImageScrollbarChange(evt, viewportId)}
|
||||
max={
|
||||
imageSliceData.numberOfSlices ? imageSliceData.numberOfSlices - 1 : 0
|
||||
}
|
||||
max={imageSliceData.numberOfSlices ? imageSliceData.numberOfSlices - 1 : 0}
|
||||
height={scrollbarHeight}
|
||||
value={imageSliceData.imageIndex}
|
||||
/>
|
||||
|
||||
+8
-20
@@ -33,26 +33,14 @@ function ViewportImageSliceLoadingIndicator({ viewportData, element }) {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
element.addEventListener(
|
||||
Enums.Events.STACK_VIEWPORT_SCROLL,
|
||||
setLoadingState
|
||||
);
|
||||
element.addEventListener(Enums.Events.STACK_VIEWPORT_SCROLL, setLoadingState);
|
||||
element.addEventListener(Enums.Events.IMAGE_LOAD_ERROR, setErrorState);
|
||||
element.addEventListener(
|
||||
Enums.Events.STACK_NEW_IMAGE,
|
||||
setFinishLoadingState
|
||||
);
|
||||
element.addEventListener(Enums.Events.STACK_NEW_IMAGE, setFinishLoadingState);
|
||||
|
||||
return () => {
|
||||
element.removeEventListener(
|
||||
Enums.Events.STACK_VIEWPORT_SCROLL,
|
||||
setLoadingState
|
||||
);
|
||||
element.removeEventListener(Enums.Events.STACK_VIEWPORT_SCROLL, setLoadingState);
|
||||
|
||||
element.removeEventListener(
|
||||
Enums.Events.STACK_NEW_IMAGE,
|
||||
setFinishLoadingState
|
||||
);
|
||||
element.removeEventListener(Enums.Events.STACK_NEW_IMAGE, setFinishLoadingState);
|
||||
|
||||
element.removeEventListener(Enums.Events.IMAGE_LOAD_ERROR, setErrorState);
|
||||
};
|
||||
@@ -61,8 +49,8 @@ function ViewportImageSliceLoadingIndicator({ viewportData, element }) {
|
||||
if (error) {
|
||||
return (
|
||||
<>
|
||||
<div className="bg-black opacity-50 absolute h-full w-full top-0 left-0">
|
||||
<div className="flex transparent items-center justify-center w-full h-full">
|
||||
<div className="absolute top-0 left-0 h-full w-full bg-black opacity-50">
|
||||
<div className="transparent flex h-full w-full items-center justify-center">
|
||||
<p className="text-primary-light text-xl font-light">
|
||||
<h4>Error Loading Image</h4>
|
||||
<p>An error has occurred.</p>
|
||||
@@ -78,8 +66,8 @@ function ViewportImageSliceLoadingIndicator({ viewportData, element }) {
|
||||
return (
|
||||
// IMPORTANT: we need to use the pointer-events-none class to prevent the loading indicator from
|
||||
// interacting with the mouse, since scrolling should propagate to the viewport underneath
|
||||
<div className="pointer-events-none bg-black opacity-50 absolute h-full w-full top-0 left-0">
|
||||
<div className="flex transparent items-center justify-center w-full h-full">
|
||||
<div className="pointer-events-none absolute top-0 left-0 h-full w-full bg-black opacity-50">
|
||||
<div className="transparent flex h-full w-full items-center justify-center">
|
||||
<p className="text-primary-light text-xl font-light">Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,10 +13,7 @@ import { vec3 } from 'gl-matrix';
|
||||
|
||||
import './ViewportOrientationMarkers.css';
|
||||
|
||||
const {
|
||||
getOrientationStringLPS,
|
||||
invertOrientationStringLPS,
|
||||
} = utilities.orientation;
|
||||
const { getOrientationStringLPS, invertOrientationStringLPS } = utilities.orientation;
|
||||
|
||||
function ViewportOrientationMarkers({
|
||||
element,
|
||||
@@ -33,9 +30,7 @@ function ViewportOrientationMarkers({
|
||||
const { cornerstoneViewportService } = servicesManager.services;
|
||||
|
||||
useEffect(() => {
|
||||
const cameraModifiedListener = (
|
||||
evt: Types.EventTypes.CameraModifiedEvent
|
||||
) => {
|
||||
const cameraModifiedListener = (evt: Types.EventTypes.CameraModifiedEvent) => {
|
||||
const { rotation, previousCamera, camera } = evt.detail;
|
||||
|
||||
if (rotation !== undefined) {
|
||||
@@ -57,16 +52,10 @@ function ViewportOrientationMarkers({
|
||||
}
|
||||
};
|
||||
|
||||
element.addEventListener(
|
||||
Enums.Events.CAMERA_MODIFIED,
|
||||
cameraModifiedListener
|
||||
);
|
||||
element.addEventListener(Enums.Events.CAMERA_MODIFIED, cameraModifiedListener);
|
||||
|
||||
return () => {
|
||||
element.removeEventListener(
|
||||
Enums.Events.CAMERA_MODIFIED,
|
||||
cameraModifiedListener
|
||||
);
|
||||
element.removeEventListener(Enums.Events.CAMERA_MODIFIED, cameraModifiedListener);
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -85,8 +74,7 @@ function ViewportOrientationMarkers({
|
||||
return false;
|
||||
}
|
||||
|
||||
({ rowCosines, columnCosines } =
|
||||
metaData.get('imagePlaneModule', imageId) || {});
|
||||
({ rowCosines, columnCosines } = metaData.get('imagePlaneModule', imageId) || {});
|
||||
} else {
|
||||
if (!element || !getEnabledElement(element)) {
|
||||
return '';
|
||||
@@ -124,9 +112,7 @@ function ViewportOrientationMarkers({
|
||||
|
||||
// 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;
|
||||
const isLight = backgroundColor ? csUtils.isEqual(backgroundColor, [1, 1, 1]) : false;
|
||||
|
||||
return orientationMarkers.map((m, index) => (
|
||||
<div
|
||||
@@ -172,13 +158,7 @@ ViewportOrientationMarkers.defaultProps = {
|
||||
* @param {*} rotation in degrees
|
||||
* @returns
|
||||
*/
|
||||
function _getOrientationMarkers(
|
||||
rowCosines,
|
||||
columnCosines,
|
||||
rotation,
|
||||
flipVertical,
|
||||
flipHorizontal
|
||||
) {
|
||||
function _getOrientationMarkers(rowCosines, columnCosines, rotation, flipVertical, flipHorizontal) {
|
||||
const rowString = getOrientationStringLPS(rowCosines);
|
||||
const columnString = getOrientationStringLPS(columnCosines);
|
||||
const oppositeRowString = invertOrientationStringLPS(rowString);
|
||||
|
||||
@@ -14,10 +14,7 @@ function CornerstoneViewportOverlay({
|
||||
viewportId,
|
||||
servicesManager,
|
||||
}) {
|
||||
const {
|
||||
cornerstoneViewportService,
|
||||
toolbarService,
|
||||
} = servicesManager.services;
|
||||
const { cornerstoneViewportService, toolbarService } = servicesManager.services;
|
||||
const [voi, setVOI] = useState({ windowCenter: null, windowWidth: null });
|
||||
const [scale, setScale] = useState(1);
|
||||
const [activeTools, setActiveTools] = useState([]);
|
||||
@@ -60,10 +57,7 @@ function CornerstoneViewportOverlay({
|
||||
}
|
||||
|
||||
const { lower, upper } = range;
|
||||
const { windowWidth, windowCenter } = utilities.windowLevel.toWindowLevel(
|
||||
lower,
|
||||
upper
|
||||
);
|
||||
const { windowWidth, windowCenter } = utilities.windowLevel.toWindowLevel(lower, upper);
|
||||
|
||||
setVOI({ windowCenter, windowWidth });
|
||||
};
|
||||
@@ -86,9 +80,7 @@ function CornerstoneViewportOverlay({
|
||||
previousCamera.parallelScale !== camera.parallelScale ||
|
||||
previousCamera.scale !== camera.scale
|
||||
) {
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(
|
||||
viewportId
|
||||
);
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
|
||||
if (!viewport) {
|
||||
return;
|
||||
@@ -107,8 +99,7 @@ function CornerstoneViewportOverlay({
|
||||
|
||||
const { spacing } = imageData;
|
||||
// convert parallel scale to scale
|
||||
const scale =
|
||||
(element.clientHeight * spacing[0] * 0.5) / camera.parallelScale;
|
||||
const scale = (element.clientHeight * spacing[0] * 0.5) / camera.parallelScale;
|
||||
setScale(scale);
|
||||
}
|
||||
};
|
||||
@@ -199,9 +190,7 @@ function CornerstoneViewportOverlay({
|
||||
|
||||
// Todo: probably this can be done in a better way in which we identify bright
|
||||
// background
|
||||
const isLight = backgroundColor
|
||||
? utilities.isEqual(backgroundColor, [1, 1, 1])
|
||||
: false;
|
||||
const isLight = backgroundColor ? utilities.isEqual(backgroundColor, [1, 1, 1]) : false;
|
||||
|
||||
return (
|
||||
<ViewportOverlay
|
||||
@@ -251,9 +240,7 @@ function _getInstanceNumberFromVolume(
|
||||
const volume = volumes[0];
|
||||
const { direction, imageIds } = volume;
|
||||
|
||||
const cornerstoneViewport = cornerstoneViewportService.getCornerstoneViewport(
|
||||
viewportId
|
||||
);
|
||||
const cornerstoneViewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
|
||||
if (!cornerstoneViewport) {
|
||||
return;
|
||||
@@ -276,8 +263,7 @@ function _getInstanceNumberFromVolume(
|
||||
return {};
|
||||
}
|
||||
|
||||
const { instanceNumber } =
|
||||
metaData.get('generalImageModule', imageId) || {};
|
||||
const { instanceNumber } = metaData.get('generalImageModule', imageId) || {};
|
||||
return parseInt(instanceNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,18 +79,12 @@ export function formatPN(name) {
|
||||
*/
|
||||
export function getCompression(imageId) {
|
||||
const generalImageModule = metaData.get('generalImageModule', imageId) || {};
|
||||
const {
|
||||
lossyImageCompression,
|
||||
lossyImageCompressionRatio,
|
||||
lossyImageCompressionMethod,
|
||||
} = generalImageModule;
|
||||
const { lossyImageCompression, lossyImageCompressionRatio, lossyImageCompressionMethod } =
|
||||
generalImageModule;
|
||||
|
||||
if (lossyImageCompression === '01' && lossyImageCompressionRatio !== '') {
|
||||
const compressionMethod = lossyImageCompressionMethod || 'Lossy: ';
|
||||
const compressionRatio = formatNumberPrecision(
|
||||
lossyImageCompressionRatio,
|
||||
2
|
||||
);
|
||||
const compressionRatio = formatNumberPrecision(lossyImageCompressionRatio, 2);
|
||||
return compressionMethod + compressionRatio + ' : 1';
|
||||
}
|
||||
|
||||
|
||||
@@ -57,9 +57,7 @@ function commandsModule({
|
||||
// filter by allowed selected tools from config property (if there is any)
|
||||
const isToolAllowed =
|
||||
!optionsToUse.allowedSelectedTools ||
|
||||
optionsToUse.allowedSelectedTools.includes(
|
||||
firstAnnotationSelected?.metadata?.toolName
|
||||
);
|
||||
optionsToUse.allowedSelectedTools.includes(firstAnnotationSelected?.metadata?.toolName);
|
||||
if (isToolAllowed) {
|
||||
optionsToUse.nearbyToolData = firstAnnotationSelected;
|
||||
} else {
|
||||
@@ -89,10 +87,7 @@ function commandsModule({
|
||||
},
|
||||
|
||||
getNearbyToolData({ nearbyToolData, element, canvasCoordinates }) {
|
||||
return (
|
||||
nearbyToolData ??
|
||||
cstUtils.getAnnotationNearPoint(element, canvasCoordinates)
|
||||
);
|
||||
return nearbyToolData ?? cstUtils.getAnnotationNearPoint(element, canvasCoordinates);
|
||||
},
|
||||
getNearbyAnnotation({ element, canvasCoordinates }) {
|
||||
const nearbyToolData = actions.getNearbyToolData({
|
||||
@@ -109,18 +104,14 @@ function commandsModule({
|
||||
}
|
||||
|
||||
const { renderingEngineId, viewportId } = enabledElement;
|
||||
const toolGroup = ToolGroupManager.getToolGroupForViewport(
|
||||
viewportId,
|
||||
renderingEngineId
|
||||
);
|
||||
const toolGroup = ToolGroupManager.getToolGroupForViewport(viewportId, renderingEngineId);
|
||||
|
||||
const toolInstance = toolGroup.getToolInstance(toolName);
|
||||
|
||||
return toolInstance?.constructor?.isAnnotation ?? true;
|
||||
};
|
||||
|
||||
return nearbyToolData?.metadata?.toolName &&
|
||||
isAnnotation(nearbyToolData.metadata.toolName)
|
||||
return nearbyToolData?.metadata?.toolName && isAnnotation(nearbyToolData.metadata.toolName)
|
||||
? nearbyToolData
|
||||
: null;
|
||||
},
|
||||
@@ -153,11 +144,7 @@ function commandsModule({
|
||||
label,
|
||||
});
|
||||
|
||||
measurementService.update(
|
||||
updatedMeasurement.uid,
|
||||
updatedMeasurement,
|
||||
true
|
||||
);
|
||||
measurementService.update(updatedMeasurement.uid, updatedMeasurement, true);
|
||||
},
|
||||
false
|
||||
);
|
||||
@@ -220,20 +207,14 @@ function commandsModule({
|
||||
}
|
||||
}
|
||||
}
|
||||
measurementService.update(
|
||||
updatedMeasurement.uid,
|
||||
updatedMeasurement,
|
||||
true
|
||||
);
|
||||
measurementService.update(updatedMeasurement.uid, updatedMeasurement, true);
|
||||
},
|
||||
|
||||
// Retrieve value commands
|
||||
getActiveViewportEnabledElement: _getActiveViewportEnabledElement,
|
||||
|
||||
setViewportActive: ({ viewportId }) => {
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfo(
|
||||
viewportId
|
||||
);
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
|
||||
if (!viewportInfo) {
|
||||
console.warn('No viewport found for viewportId:', viewportId);
|
||||
return;
|
||||
@@ -249,9 +230,7 @@ function commandsModule({
|
||||
const { isCineEnabled } = cineService.getState();
|
||||
cineService.setIsCineEnabled(!isCineEnabled);
|
||||
toolbarService.setButton('Cine', { props: { isActive: !isCineEnabled } });
|
||||
viewports.forEach((_, index) =>
|
||||
cineService.setCine({ id: index, isPlaying: false })
|
||||
);
|
||||
viewports.forEach((_, index) => cineService.setCine({ id: index, isPlaying: false }));
|
||||
},
|
||||
setWindowLevel({ window, level, toolGroupId }) {
|
||||
// convert to numbers
|
||||
@@ -259,9 +238,7 @@ function commandsModule({
|
||||
const windowCenterNum = Number(level);
|
||||
|
||||
const { viewportId } = _getActiveViewportEnabledElement();
|
||||
const viewportToolGroupId = toolGroupService.getToolGroupForViewport(
|
||||
viewportId
|
||||
);
|
||||
const viewportToolGroupId = toolGroupService.getToolGroupForViewport(viewportId);
|
||||
|
||||
if (toolGroupId && toolGroupId !== viewportToolGroupId) {
|
||||
return;
|
||||
@@ -271,10 +248,7 @@ function commandsModule({
|
||||
const renderingEngine = cornerstoneViewportService.getRenderingEngine();
|
||||
const viewport = renderingEngine.getViewport(viewportId);
|
||||
|
||||
const { lower, upper } = csUtils.windowLevel.toLowHighRange(
|
||||
windowWidthNum,
|
||||
windowCenterNum
|
||||
);
|
||||
const { lower, upper } = csUtils.windowLevel.toLowHighRange(windowWidthNum, windowCenterNum);
|
||||
|
||||
viewport.setProperties({
|
||||
voiRange: {
|
||||
@@ -323,11 +297,9 @@ function commandsModule({
|
||||
return;
|
||||
}
|
||||
|
||||
const filteredViewports = Array.from(viewports.values()).filter(
|
||||
viewport => {
|
||||
return toolGroupViewportIds.includes(viewport.viewportId);
|
||||
}
|
||||
);
|
||||
const filteredViewports = Array.from(viewports.values()).filter(viewport => {
|
||||
return toolGroupViewportIds.includes(viewport.viewportId);
|
||||
});
|
||||
|
||||
if (!filteredViewports.length) {
|
||||
return;
|
||||
@@ -367,9 +339,7 @@ function commandsModule({
|
||||
showDownloadViewportModal: () => {
|
||||
const { activeViewportId } = viewportGridService.getState();
|
||||
|
||||
if (
|
||||
!cornerstoneViewportService.getCornerstoneViewport(activeViewportId)
|
||||
) {
|
||||
if (!cornerstoneViewportService.getCornerstoneViewport(activeViewportId)) {
|
||||
// Cannot download a non-cornerstone viewport (image).
|
||||
uiNotificationService.show({
|
||||
title: 'Download Image',
|
||||
@@ -508,9 +478,7 @@ function commandsModule({
|
||||
}
|
||||
viewport = enabledElement.viewport;
|
||||
} else {
|
||||
viewport = cornerstoneViewportService.getCornerstoneViewport(
|
||||
gridViewport.id
|
||||
);
|
||||
viewport = cornerstoneViewportService.getCornerstoneViewport(gridViewport.id);
|
||||
}
|
||||
|
||||
// Get number of slices
|
||||
@@ -520,14 +488,12 @@ function commandsModule({
|
||||
if (viewport instanceof StackViewport) {
|
||||
numberOfSlices = viewport.getImageIds().length;
|
||||
} else if (viewport instanceof VolumeViewport) {
|
||||
numberOfSlices = csUtils.getImageSliceDataForVolumeViewport(viewport)
|
||||
.numberOfSlices;
|
||||
numberOfSlices = csUtils.getImageSliceDataForVolumeViewport(viewport).numberOfSlices;
|
||||
} else {
|
||||
throw new Error('Unsupported viewport type');
|
||||
}
|
||||
|
||||
const jumpIndex =
|
||||
imageIndex < 0 ? numberOfSlices + imageIndex : imageIndex;
|
||||
const jumpIndex = imageIndex < 0 ? numberOfSlices + imageIndex : imageIndex;
|
||||
if (jumpIndex >= numberOfSlices || jumpIndex < 0) {
|
||||
throw new Error(`Can't jump to ${imageIndex}`);
|
||||
}
|
||||
@@ -548,15 +514,8 @@ function commandsModule({
|
||||
|
||||
cstUtils.scroll(viewport, options);
|
||||
},
|
||||
setViewportColormap: ({
|
||||
viewportId,
|
||||
displaySetInstanceUID,
|
||||
colormap,
|
||||
immediate = false,
|
||||
}) => {
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(
|
||||
viewportId
|
||||
);
|
||||
setViewportColormap: ({ viewportId, displaySetInstanceUID, colormap, immediate = false }) => {
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
|
||||
const actorEntries = viewport.getActors();
|
||||
|
||||
@@ -578,9 +537,7 @@ function commandsModule({
|
||||
const currentIndex = viewportIds.indexOf(activeViewportId);
|
||||
const nextViewportIndex =
|
||||
(currentIndex + direction + viewportIds.length) % viewportIds.length;
|
||||
viewportGridService.setActiveViewportId(
|
||||
viewportIds[nextViewportIndex] as string
|
||||
);
|
||||
viewportGridService.setActiveViewportId(viewportIds[nextViewportIndex] as string);
|
||||
},
|
||||
|
||||
toggleStackImageSync: ({ toggledState }) => {
|
||||
@@ -592,9 +549,7 @@ function commandsModule({
|
||||
},
|
||||
toggleReferenceLines: ({ toggledState }) => {
|
||||
const { activeViewportId } = viewportGridService.getState();
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfo(
|
||||
activeViewportId
|
||||
);
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfo(activeViewportId);
|
||||
|
||||
const viewportId = viewportInfo.getViewportId();
|
||||
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
|
||||
|
||||
@@ -46,17 +46,11 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
eventTarget.addEventListener(
|
||||
Enums.Events.STACK_VIEWPORT_NEW_STACK,
|
||||
cineHandler
|
||||
);
|
||||
eventTarget.addEventListener(Enums.Events.STACK_VIEWPORT_NEW_STACK, cineHandler);
|
||||
|
||||
return () => {
|
||||
cineService.setCine({ id: viewportId, isPlaying: false });
|
||||
eventTarget.removeEventListener(
|
||||
Enums.Events.STACK_VIEWPORT_NEW_STACK,
|
||||
cineHandler
|
||||
);
|
||||
eventTarget.removeEventListener(Enums.Events.STACK_VIEWPORT_NEW_STACK, cineHandler);
|
||||
};
|
||||
}, [enabledVPElement]);
|
||||
|
||||
@@ -80,7 +74,7 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
|
||||
return (
|
||||
isCineEnabled && (
|
||||
<CinePlayerComponent
|
||||
className="absolute left-1/2 -translate-x-1/2 bottom-3"
|
||||
className="absolute left-1/2 bottom-3 -translate-x-1/2"
|
||||
isPlaying={isPlaying}
|
||||
onClose={handleCineClose}
|
||||
onPlayPauseChange={isPlaying =>
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
.dicom-upload-drop-area-border-dash {
|
||||
background-image: repeating-linear-gradient(to right, #7BB2CE 0%, #7BB2CE 50%, transparent 50%, transparent 100%), repeating-linear-gradient(to right, #7BB2CE 0%, #7BB2CE 50%, transparent 50%, transparent 100%), repeating-linear-gradient(to bottom, #7BB2CE 0%, #7BB2CE 50%, transparent 50%, transparent 100%), repeating-linear-gradient(to bottom, #7BB2CE 0%, #7BB2CE 50%, transparent 50%, transparent 100%);
|
||||
background-position: left top, left bottom, left top, right top;
|
||||
background-image: repeating-linear-gradient(
|
||||
to right,
|
||||
#7bb2ce 0%,
|
||||
#7bb2ce 50%,
|
||||
transparent 50%,
|
||||
transparent 100%
|
||||
),
|
||||
repeating-linear-gradient(to right, #7bb2ce 0%, #7bb2ce 50%, transparent 50%, transparent 100%),
|
||||
repeating-linear-gradient(to bottom, #7bb2ce 0%, #7bb2ce 50%, transparent 50%, transparent 100%),
|
||||
repeating-linear-gradient(to bottom, #7bb2ce 0%, #7bb2ce 50%, transparent 50%, transparent 100%);
|
||||
background-position:
|
||||
left top,
|
||||
left bottom,
|
||||
left top,
|
||||
right top;
|
||||
background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
|
||||
background-size: 20px 3px, 20px 3px, 3px 20px, 3px 20px;
|
||||
background-size:
|
||||
20px 3px,
|
||||
20px 3px,
|
||||
3px 20px,
|
||||
3px 20px;
|
||||
}
|
||||
@@ -14,19 +14,13 @@ type DicomUploadProps = {
|
||||
onStarted: () => void;
|
||||
};
|
||||
|
||||
function DicomUpload({
|
||||
dataSource,
|
||||
onComplete,
|
||||
onStarted,
|
||||
}: DicomUploadProps): ReactElement {
|
||||
function DicomUpload({ dataSource, onComplete, onStarted }: DicomUploadProps): ReactElement {
|
||||
const baseClassNames = 'min-h-[480px] flex flex-col bg-black select-none';
|
||||
const [dicomFileUploaderArr, setDicomFileUploaderArr] = useState([]);
|
||||
|
||||
const onDrop = useCallback(async acceptedFiles => {
|
||||
onStarted();
|
||||
setDicomFileUploaderArr(
|
||||
acceptedFiles.map(file => new DicomFileUploader(file, dataSource))
|
||||
);
|
||||
setDicomFileUploaderArr(acceptedFiles.map(file => new DicomFileUploader(file, dataSource)));
|
||||
}, []);
|
||||
|
||||
const getDropZoneComponent = (): ReactElement => {
|
||||
@@ -40,20 +34,29 @@ function DicomUpload({
|
||||
{({ getRootProps }) => (
|
||||
<div
|
||||
{...getRootProps()}
|
||||
className="m-5 dicom-upload-drop-area-border-dash flex flex-col items-center justify-center h-full"
|
||||
className="dicom-upload-drop-area-border-dash m-5 flex h-full flex-col items-center justify-center"
|
||||
>
|
||||
<div className="flex gap-3">
|
||||
<Dropzone onDrop={onDrop} noDrag>
|
||||
<Dropzone
|
||||
onDrop={onDrop}
|
||||
noDrag
|
||||
>
|
||||
{({ getRootProps, getInputProps }) => (
|
||||
<div {...getRootProps()}>
|
||||
<Button disabled={false} onClick={() => {}}>
|
||||
<Button
|
||||
disabled={false}
|
||||
onClick={() => {}}
|
||||
>
|
||||
{'Add files'}
|
||||
<input {...getInputProps()} />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</Dropzone>
|
||||
<Dropzone onDrop={onDrop} noDrag>
|
||||
<Dropzone
|
||||
onDrop={onDrop}
|
||||
noDrag
|
||||
>
|
||||
{({ getRootProps, getInputProps }) => (
|
||||
<div {...getRootProps()}>
|
||||
<Button
|
||||
@@ -73,9 +76,7 @@ function DicomUpload({
|
||||
</Dropzone>
|
||||
</div>
|
||||
<div className="pt-5">or drag images or folders here</div>
|
||||
<div className="pt-3 text-aqua-pale text-lg">
|
||||
(DICOM files supported)
|
||||
</div>
|
||||
<div className="text-aqua-pale pt-3 text-lg">(DICOM files supported)</div>
|
||||
</div>
|
||||
)}
|
||||
</Dropzone>
|
||||
@@ -92,9 +93,7 @@ function DicomUpload({
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className={classNames('h-[480px]', baseClassNames)}>
|
||||
{getDropZoneComponent()}
|
||||
</div>
|
||||
<div className={classNames('h-[480px]', baseClassNames)}>{getDropZoneComponent()}</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
ReactElement,
|
||||
} from 'react';
|
||||
import React, { useCallback, useEffect, useRef, useState, ReactElement } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, Icon, ProgressLoadingBar } from '@ohif/ui';
|
||||
import DicomFileUploader, {
|
||||
@@ -39,18 +33,14 @@ const BASE_INTERVAL_TIME = 15000;
|
||||
// calculate the upload rate.
|
||||
const UPLOAD_RATE_THRESHOLD = 75;
|
||||
|
||||
const NO_WRAP_ELLIPSIS_CLASS_NAMES =
|
||||
'text-ellipsis whitespace-nowrap overflow-hidden';
|
||||
const NO_WRAP_ELLIPSIS_CLASS_NAMES = 'text-ellipsis whitespace-nowrap overflow-hidden';
|
||||
|
||||
function DicomUploadProgress({
|
||||
dicomFileUploaderArr,
|
||||
onComplete,
|
||||
}: DicomUploadProgressProps): ReactElement {
|
||||
const [totalUploadSize] = useState(
|
||||
dicomFileUploaderArr.reduce(
|
||||
(acc, fileUploader) => acc + fileUploader.getFileSize(),
|
||||
0
|
||||
)
|
||||
dicomFileUploaderArr.reduce((acc, fileUploader) => acc + fileUploader.getFileSize(), 0)
|
||||
);
|
||||
|
||||
const currentUploadSizeRef = useRef<number>(0);
|
||||
@@ -83,15 +73,13 @@ function DicomUploadProgress({
|
||||
let intervalStartTime = Date.now();
|
||||
|
||||
const setUploadRateRef = () => {
|
||||
const uploadSizeFromStartOfInterval =
|
||||
currentUploadSizeRef.current - intervalStartUploadSize;
|
||||
const uploadSizeFromStartOfInterval = currentUploadSizeRef.current - intervalStartUploadSize;
|
||||
|
||||
const now = Date.now();
|
||||
const timeSinceStartOfInterval = now - intervalStartTime;
|
||||
|
||||
// Calculate and set the upload rate (ref)
|
||||
uploadRateRef.current =
|
||||
uploadSizeFromStartOfInterval / timeSinceStartOfInterval;
|
||||
uploadRateRef.current = uploadSizeFromStartOfInterval / timeSinceStartOfInterval;
|
||||
|
||||
// Reset the interval starting values.
|
||||
intervalStartUploadSize = currentUploadSizeRef.current;
|
||||
@@ -134,28 +122,19 @@ function DicomUploadProgress({
|
||||
const updateProgress = (percentComplete: number) => {
|
||||
const previousFileUploadSize = currentFileUploadSize;
|
||||
|
||||
currentFileUploadSize = Math.round(
|
||||
(percentComplete / 100) * fileUploader.getFileSize()
|
||||
);
|
||||
currentFileUploadSize = Math.round((percentComplete / 100) * fileUploader.getFileSize());
|
||||
|
||||
currentUploadSizeRef.current = Math.min(
|
||||
totalUploadSize,
|
||||
currentUploadSizeRef.current -
|
||||
previousFileUploadSize +
|
||||
currentFileUploadSize
|
||||
currentUploadSizeRef.current - previousFileUploadSize + currentFileUploadSize
|
||||
);
|
||||
|
||||
setPercentComplete(
|
||||
(currentUploadSizeRef.current / totalUploadSize) * 100
|
||||
);
|
||||
setPercentComplete((currentUploadSizeRef.current / totalUploadSize) * 100);
|
||||
|
||||
if (uploadRateRef.current !== 0) {
|
||||
const uploadSizeRemaining =
|
||||
totalUploadSize - currentUploadSizeRef.current;
|
||||
const uploadSizeRemaining = totalUploadSize - currentUploadSizeRef.current;
|
||||
|
||||
const timeRemaining = Math.round(
|
||||
uploadSizeRemaining / uploadRateRef.current
|
||||
);
|
||||
const timeRemaining = Math.round(uploadSizeRemaining / uploadRateRef.current);
|
||||
|
||||
if (currentTimeRemaining === null) {
|
||||
currentTimeRemaining = timeRemaining;
|
||||
@@ -168,9 +147,7 @@ function DicomUploadProgress({
|
||||
// due to rounding, inaccuracies in the estimate and slight variations
|
||||
// in upload rates over time.
|
||||
if (timeRemaining < ONE_MINUTE) {
|
||||
const currentSecondsRemaining = Math.ceil(
|
||||
currentTimeRemaining / ONE_SECOND
|
||||
);
|
||||
const currentSecondsRemaining = Math.ceil(currentTimeRemaining / ONE_SECOND);
|
||||
const secondsRemaining = Math.ceil(timeRemaining / ONE_SECOND);
|
||||
const delta = secondsRemaining - currentSecondsRemaining;
|
||||
if (delta < 0 || delta > 2) {
|
||||
@@ -181,9 +158,7 @@ function DicomUploadProgress({
|
||||
}
|
||||
|
||||
if (timeRemaining < ONE_HOUR) {
|
||||
const currentMinutesRemaining = Math.ceil(
|
||||
currentTimeRemaining / ONE_MINUTE
|
||||
);
|
||||
const currentMinutesRemaining = Math.ceil(currentTimeRemaining / ONE_MINUTE);
|
||||
const minutesRemaining = Math.ceil(timeRemaining / ONE_MINUTE);
|
||||
const delta = minutesRemaining - currentMinutesRemaining;
|
||||
if (delta < 0 || delta > 2) {
|
||||
@@ -199,9 +174,7 @@ function DicomUploadProgress({
|
||||
}
|
||||
};
|
||||
|
||||
const progressCallback = (
|
||||
progressEvent: DicomFileUploaderProgressEvent
|
||||
) => {
|
||||
const progressCallback = (progressEvent: DicomFileUploaderProgressEvent) => {
|
||||
updateProgress(progressEvent.percentComplete);
|
||||
};
|
||||
|
||||
@@ -249,16 +222,12 @@ function DicomUploadProgress({
|
||||
|
||||
if (timeRemaining < ONE_MINUTE) {
|
||||
const secondsRemaining = Math.ceil(timeRemaining / ONE_SECOND);
|
||||
return `${secondsRemaining} ${
|
||||
secondsRemaining === 1 ? 'second' : 'seconds'
|
||||
}`;
|
||||
return `${secondsRemaining} ${secondsRemaining === 1 ? 'second' : 'seconds'}`;
|
||||
}
|
||||
|
||||
if (timeRemaining < ONE_HOUR) {
|
||||
const minutesRemaining = Math.ceil(timeRemaining / ONE_MINUTE);
|
||||
return `${minutesRemaining} ${
|
||||
minutesRemaining === 1 ? 'minute' : 'minutes'
|
||||
}`;
|
||||
return `${minutesRemaining} ${minutesRemaining === 1 ? 'minute' : 'minutes'}`;
|
||||
}
|
||||
|
||||
const hoursRemaining = Math.ceil(timeRemaining / ONE_HOUR);
|
||||
@@ -278,9 +247,7 @@ function DicomUploadProgress({
|
||||
const showInfiniteProgressBar = useCallback((): boolean => {
|
||||
return (
|
||||
getPercentCompleteRounded() < 1 &&
|
||||
(progressBarContainerRef?.current?.offsetWidth ?? 0) *
|
||||
(percentComplete / 100) <
|
||||
1
|
||||
(progressBarContainerRef?.current?.offsetWidth ?? 0) * (percentComplete / 100) < 1
|
||||
);
|
||||
}, [getPercentCompleteRounded, percentComplete]);
|
||||
|
||||
@@ -300,15 +267,17 @@ function DicomUploadProgress({
|
||||
|
||||
const getNumCompletedAndTimeRemainingComponent = (): ReactElement => {
|
||||
return (
|
||||
<div className="text-lg px-1 pb-4 h-14 flex bg-primary-dark items-center">
|
||||
<div className="bg-primary-dark flex h-14 items-center px-1 pb-4 text-lg">
|
||||
{numFilesCompleted === dicomFileUploaderArr.length ? (
|
||||
<>
|
||||
<span className={NO_WRAP_ELLIPSIS_CLASS_NAMES}>{`${
|
||||
dicomFileUploaderArr.length
|
||||
} ${
|
||||
<span className={NO_WRAP_ELLIPSIS_CLASS_NAMES}>{`${dicomFileUploaderArr.length} ${
|
||||
dicomFileUploaderArr.length > 1 ? 'files' : 'file'
|
||||
} completed.`}</span>
|
||||
<Button disabled={false} className="ml-auto" onClick={onComplete}>
|
||||
<Button
|
||||
disabled={false}
|
||||
className="ml-auto"
|
||||
onClick={onComplete}
|
||||
>
|
||||
{'Close'}
|
||||
</Button>
|
||||
</>
|
||||
@@ -320,18 +289,14 @@ function DicomUploadProgress({
|
||||
>
|
||||
{`${numFilesCompleted} of ${dicomFileUploaderArr.length}`}
|
||||
</span>
|
||||
<span className={NO_WRAP_ELLIPSIS_CLASS_NAMES}>{' files completed.'} </span>
|
||||
<span className={NO_WRAP_ELLIPSIS_CLASS_NAMES}>
|
||||
{' files completed.'}
|
||||
</span>
|
||||
<span className={NO_WRAP_ELLIPSIS_CLASS_NAMES}>
|
||||
{timeRemaining
|
||||
? `Less than ${getFormattedTimeRemaining()} remaining. `
|
||||
: ''}
|
||||
{timeRemaining ? `Less than ${getFormattedTimeRemaining()} remaining. ` : ''}
|
||||
</span>
|
||||
<span
|
||||
className={classNames(
|
||||
NO_WRAP_ELLIPSIS_CLASS_NAMES,
|
||||
'cursor-pointer text-primary-active hover:text-primary-light active:text-aqua-pale ml-auto'
|
||||
'text-primary-active hover:text-primary-light active:text-aqua-pale ml-auto cursor-pointer'
|
||||
)}
|
||||
onClick={cancelAllUploads}
|
||||
>
|
||||
@@ -345,14 +310,13 @@ function DicomUploadProgress({
|
||||
|
||||
const getShowFailedOnlyIconComponent = (): ReactElement => {
|
||||
return (
|
||||
<div className="ml-auto flex justify-center w-6">
|
||||
<div className="ml-auto flex w-6 justify-center">
|
||||
{numFails > 0 && (
|
||||
<div
|
||||
onClick={() =>
|
||||
setShowFailedOnly(currentShowFailedOnly => !currentShowFailedOnly)
|
||||
}
|
||||
>
|
||||
<Icon className="cursor-pointer" name="icon-status-alert"></Icon>
|
||||
<div onClick={() => setShowFailedOnly(currentShowFailedOnly => !currentShowFailedOnly)}>
|
||||
<Icon
|
||||
className="cursor-pointer"
|
||||
name="icon-status-alert"
|
||||
></Icon>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -361,31 +325,28 @@ function DicomUploadProgress({
|
||||
|
||||
const getPercentCompleteComponent = (): ReactElement => {
|
||||
return (
|
||||
<div className="overflow-y-scroll ohif-scrollbar px-2 border-b border-secondary-light">
|
||||
<div className="flex w-full p-2.5 items-center min-h-14">
|
||||
<div className="ohif-scrollbar border-secondary-light overflow-y-scroll border-b px-2">
|
||||
<div className="min-h-14 flex w-full items-center p-2.5">
|
||||
{numFilesCompleted === dicomFileUploaderArr.length ? (
|
||||
<>
|
||||
<div className="text-xl text-primary-light">
|
||||
<div className="text-primary-light text-xl">
|
||||
{numFails > 0
|
||||
? `Completed with ${numFails} ${
|
||||
numFails > 1 ? 'errors' : 'error'
|
||||
}!`
|
||||
? `Completed with ${numFails} ${numFails > 1 ? 'errors' : 'error'}!`
|
||||
: 'Completed!'}
|
||||
</div>
|
||||
{getShowFailedOnlyIconComponent()}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div ref={progressBarContainerRef} className="flex-grow">
|
||||
<div
|
||||
ref={progressBarContainerRef}
|
||||
className="flex-grow"
|
||||
>
|
||||
<ProgressLoadingBar
|
||||
progress={
|
||||
showInfiniteProgressBar()
|
||||
? undefined
|
||||
: Math.min(100, percentComplete)
|
||||
}
|
||||
progress={showInfiniteProgressBar() ? undefined : Math.min(100, percentComplete)}
|
||||
></ProgressLoadingBar>
|
||||
</div>
|
||||
<div className="w-24 ml-1 flex items-center">
|
||||
<div className="ml-1 flex w-24 items-center">
|
||||
<div className="w-10 text-right">{`${getPercentCompleteRounded()}%`}</div>
|
||||
{getShowFailedOnlyIconComponent()}
|
||||
</div>
|
||||
@@ -397,16 +358,15 @@ function DicomUploadProgress({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col grow">
|
||||
<div className="flex grow flex-col">
|
||||
{getNumCompletedAndTimeRemainingComponent()}
|
||||
<div className="flex flex-col bg-black text-lg overflow-hidden grow">
|
||||
<div className="flex grow flex-col overflow-hidden bg-black text-lg">
|
||||
{getPercentCompleteComponent()}
|
||||
<div className="overflow-y-scroll ohif-scrollbar px-2 grow h-1">
|
||||
<div className="ohif-scrollbar h-1 grow overflow-y-scroll px-2">
|
||||
{dicomFileUploaderArr
|
||||
.filter(
|
||||
dicomFileUploader =>
|
||||
!showFailedOnly ||
|
||||
dicomFileUploader.getStatus() === UploadStatus.Failed
|
||||
!showFailedOnly || dicomFileUploader.getStatus() === UploadStatus.Failed
|
||||
)
|
||||
.map(dicomFileUploader => (
|
||||
<DicomUploadProgressItem
|
||||
@@ -421,9 +381,7 @@ function DicomUploadProgress({
|
||||
}
|
||||
|
||||
DicomUploadProgress.propTypes = {
|
||||
dicomFileUploaderArr: PropTypes.arrayOf(
|
||||
PropTypes.instanceOf(DicomFileUploader)
|
||||
).isRequired,
|
||||
dicomFileUploaderArr: PropTypes.arrayOf(PropTypes.instanceOf(DicomFileUploader)).isRequired,
|
||||
onComplete: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
import React, {
|
||||
ReactElement,
|
||||
memo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import React, { ReactElement, memo, useCallback, useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import DicomFileUploader, {
|
||||
DicomFileUploaderProgressEvent,
|
||||
@@ -21,9 +15,7 @@ type DicomUploadProgressItemProps = {
|
||||
// eslint-disable-next-line react/display-name
|
||||
const DicomUploadProgressItem = memo(
|
||||
({ dicomFileUploader }: DicomUploadProgressItemProps): ReactElement => {
|
||||
const [percentComplete, setPercentComplete] = useState(
|
||||
dicomFileUploader.getPercentComplete()
|
||||
);
|
||||
const [percentComplete, setPercentComplete] = useState(dicomFileUploader.getPercentComplete());
|
||||
const [failedReason, setFailedReason] = useState('');
|
||||
const [status, setStatus] = useState(dicomFileUploader.getStatus());
|
||||
|
||||
@@ -62,7 +54,10 @@ const DicomUploadProgressItem = memo(
|
||||
switch (dicomFileUploader.getStatus()) {
|
||||
case UploadStatus.Success:
|
||||
return (
|
||||
<Icon name="status-tracked" className="text-primary-light"></Icon>
|
||||
<Icon
|
||||
name="status-tracked"
|
||||
className="text-primary-light"
|
||||
></Icon>
|
||||
);
|
||||
case UploadStatus.InProgress:
|
||||
return <Icon name="icon-transferring"></Icon>;
|
||||
@@ -76,27 +71,25 @@ const DicomUploadProgressItem = memo(
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex w-full p-2.5 text-lg min-h-14 items-center border-b border-secondary-light overflow-hidden">
|
||||
<div className="flex flex-col gap-1 self-top w-0 grow shrink">
|
||||
<div className="min-h-14 border-secondary-light flex w-full items-center overflow-hidden border-b p-2.5 text-lg">
|
||||
<div className="self-top flex w-0 shrink grow flex-col gap-1">
|
||||
<div className="flex gap-4">
|
||||
<div className="flex w-6 justify-center items-center shrink-0">
|
||||
{getStatusIcon()}
|
||||
</div>
|
||||
<div className="text-ellipsis whitespace-nowrap overflow-hidden">
|
||||
<div className="flex w-6 shrink-0 items-center justify-center">{getStatusIcon()}</div>
|
||||
<div className="overflow-hidden text-ellipsis whitespace-nowrap">
|
||||
{dicomFileUploader.getFileName()}
|
||||
</div>
|
||||
</div>
|
||||
{failedReason && <div className="pl-10">{failedReason}</div>}
|
||||
</div>
|
||||
<div className="w-24 flex items-center">
|
||||
<div className="flex w-24 items-center">
|
||||
{!isComplete() && (
|
||||
<>
|
||||
{dicomFileUploader.getStatus() === UploadStatus.InProgress && (
|
||||
<div className="w-10 text-right">{percentComplete}%</div>
|
||||
)}
|
||||
<div className="flex cursor-pointer ml-auto">
|
||||
<div className="ml-auto flex cursor-pointer">
|
||||
<Icon
|
||||
className="self-center text-primary-active"
|
||||
className="text-primary-active self-center"
|
||||
name="close"
|
||||
onClick={cancelUpload}
|
||||
/>
|
||||
|
||||
@@ -31,9 +31,7 @@ import { measurementMappingUtils } from './utils/measurementServiceMappings';
|
||||
import type { PublicViewportOptions } from './services/ViewportService/Viewport';
|
||||
|
||||
const Component = React.lazy(() => {
|
||||
return import(
|
||||
/* webpackPrefetch: true */ './Viewport/OHIFCornerstoneViewport'
|
||||
);
|
||||
return import(/* webpackPrefetch: true */ './Viewport/OHIFCornerstoneViewport');
|
||||
});
|
||||
|
||||
const OHIFCornerstoneViewport = props => {
|
||||
@@ -69,9 +67,7 @@ const cornerstoneExtension: Types.Extensions.Extension = {
|
||||
*
|
||||
* @param configuration.csToolsConfig - Passed directly to `initCornerstoneTools`
|
||||
*/
|
||||
preRegistration: function (
|
||||
props: Types.Extensions.ExtensionParams
|
||||
): Promise<void> {
|
||||
preRegistration: function (props: Types.Extensions.ExtensionParams): Promise<void> {
|
||||
const { servicesManager } = props;
|
||||
servicesManager.registerService(CornerstoneViewportService.REGISTRATION);
|
||||
servicesManager.registerService(ToolGroupService.REGISTRATION);
|
||||
@@ -139,5 +135,10 @@ const cornerstoneExtension: Types.Extensions.Extension = {
|
||||
};
|
||||
|
||||
export type { PublicViewportOptions };
|
||||
export { measurementMappingUtils, CornerstoneExtensionTypes, toolNames , getActiveViewportEnabledElement};
|
||||
export {
|
||||
measurementMappingUtils,
|
||||
CornerstoneExtensionTypes,
|
||||
toolNames,
|
||||
getActiveViewportEnabledElement,
|
||||
};
|
||||
export default cornerstoneExtension;
|
||||
@@ -49,8 +49,7 @@ export default async function init({
|
||||
...cornerstone.getConfiguration(),
|
||||
rendering: {
|
||||
...cornerstone.getConfiguration().rendering,
|
||||
strictZSpacingForVolumeViewport:
|
||||
appConfig.strictZSpacingForVolumeViewport,
|
||||
strictZSpacingForVolumeViewport: appConfig.strictZSpacingForVolumeViewport,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -62,10 +61,7 @@ export default async function init({
|
||||
|
||||
initCornerstoneTools();
|
||||
|
||||
Settings.getRuntimeSettings().set(
|
||||
'useCursors',
|
||||
Boolean(appConfig.useCursors)
|
||||
);
|
||||
Settings.getRuntimeSettings().set('useCursors', Boolean(appConfig.useCursors));
|
||||
|
||||
const {
|
||||
userAuthenticationService,
|
||||
@@ -84,22 +80,15 @@ export default async function init({
|
||||
window.extensionManager = extensionManager;
|
||||
window.commandsManager = commandsManager;
|
||||
|
||||
if (
|
||||
appConfig.showWarningMessageForCrossOrigin &&
|
||||
!window.crossOriginIsolated
|
||||
) {
|
||||
if (appConfig.showWarningMessageForCrossOrigin && !window.crossOriginIsolated) {
|
||||
uiNotificationService.show({
|
||||
title: 'Cross Origin Isolation',
|
||||
message:
|
||||
'Cross Origin Isolation is not enabled, volume rendering will not work (e.g., MPR)',
|
||||
message: 'Cross Origin Isolation is not enabled, volume rendering will not work (e.g., MPR)',
|
||||
type: 'warning',
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
appConfig.showCPUFallbackMessage &&
|
||||
cornerstone.getShouldUseCPURendering()
|
||||
) {
|
||||
if (appConfig.showCPUFallbackMessage && cornerstone.getShouldUseCPURendering()) {
|
||||
_showCPURenderingModal(uiModalService, hangingProtocolService);
|
||||
}
|
||||
|
||||
@@ -119,18 +108,14 @@ export default async function init({
|
||||
clearOnModeExit: true,
|
||||
});
|
||||
|
||||
const labelmapRepresentation =
|
||||
cornerstoneTools.Enums.SegmentationRepresentations.Labelmap;
|
||||
const labelmapRepresentation = cornerstoneTools.Enums.SegmentationRepresentations.Labelmap;
|
||||
|
||||
cornerstoneTools.segmentation.config.setGlobalRepresentationConfig(
|
||||
labelmapRepresentation,
|
||||
{
|
||||
fillAlpha: 0.3,
|
||||
fillAlphaInactive: 0.2,
|
||||
outlineOpacity: 1,
|
||||
outlineOpacityInactive: 0.65,
|
||||
}
|
||||
);
|
||||
cornerstoneTools.segmentation.config.setGlobalRepresentationConfig(labelmapRepresentation, {
|
||||
fillAlpha: 0.3,
|
||||
fillAlphaInactive: 0.2,
|
||||
outlineOpacity: 1,
|
||||
outlineOpacityInactive: 0.65,
|
||||
});
|
||||
|
||||
const metadataProvider = OHIF.classes.MetadataProvider;
|
||||
|
||||
@@ -139,14 +124,8 @@ export default async function init({
|
||||
cornerstoneStreamingImageVolumeLoader
|
||||
);
|
||||
|
||||
hangingProtocolService.registerImageLoadStrategy(
|
||||
'interleaveCenter',
|
||||
interleaveCenterLoader
|
||||
);
|
||||
hangingProtocolService.registerImageLoadStrategy(
|
||||
'interleaveTopToBottom',
|
||||
interleaveTopToBottom
|
||||
);
|
||||
hangingProtocolService.registerImageLoadStrategy('interleaveCenter', interleaveCenterLoader);
|
||||
hangingProtocolService.registerImageLoadStrategy('interleaveTopToBottom', interleaveTopToBottom);
|
||||
hangingProtocolService.registerImageLoadStrategy('nth', nthLoader);
|
||||
|
||||
// add metadata providers
|
||||
@@ -166,9 +145,7 @@ export default async function init({
|
||||
initWADOImageLoader(userAuthenticationService, appConfig, extensionManager);
|
||||
|
||||
/* Measurement Service */
|
||||
this.measurementServiceSource = connectToolsToMeasurementService(
|
||||
servicesManager
|
||||
);
|
||||
this.measurementServiceSource = connectToolsToMeasurementService(servicesManager);
|
||||
|
||||
initCineService(cineService);
|
||||
|
||||
@@ -178,31 +155,18 @@ export default async function init({
|
||||
volumeInputArrayMap => {
|
||||
for (const entry of volumeInputArrayMap.entries()) {
|
||||
const [viewportId, volumeInputArray] = entry;
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(
|
||||
viewportId
|
||||
);
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
|
||||
const ohifViewport = cornerstoneViewportService.getViewportInfo(
|
||||
viewportId
|
||||
);
|
||||
const ohifViewport = cornerstoneViewportService.getViewportInfo(viewportId);
|
||||
|
||||
const {
|
||||
lutPresentationStore,
|
||||
positionPresentationStore,
|
||||
} = stateSyncService.getState();
|
||||
const { lutPresentationStore, positionPresentationStore } = stateSyncService.getState();
|
||||
const { presentationIds } = ohifViewport.getViewportOptions();
|
||||
const presentations = {
|
||||
positionPresentation:
|
||||
positionPresentationStore[presentationIds?.positionPresentationId],
|
||||
lutPresentation:
|
||||
lutPresentationStore[presentationIds?.lutPresentationId],
|
||||
positionPresentation: positionPresentationStore[presentationIds?.positionPresentationId],
|
||||
lutPresentation: lutPresentationStore[presentationIds?.lutPresentationId],
|
||||
};
|
||||
|
||||
cornerstoneViewportService.setVolumesForViewport(
|
||||
viewport,
|
||||
volumeInputArray,
|
||||
presentations
|
||||
);
|
||||
cornerstoneViewportService.setVolumesForViewport(viewport, volumeInputArray, presentations);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -225,9 +189,7 @@ export default async function init({
|
||||
|
||||
const resetCrosshairs = evt => {
|
||||
const { element } = evt.detail;
|
||||
const { viewportId, renderingEngineId } = cornerstone.getEnabledElement(
|
||||
element
|
||||
);
|
||||
const { viewportId, renderingEngineId } = cornerstone.getEnabledElement(element);
|
||||
|
||||
const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroupForViewport(
|
||||
viewportId,
|
||||
@@ -253,10 +215,7 @@ export default async function init({
|
||||
const { element } = evt.detail;
|
||||
element.addEventListener(EVENTS.CAMERA_RESET, resetCrosshairs);
|
||||
|
||||
eventTarget.addEventListener(
|
||||
EVENTS.STACK_VIEWPORT_NEW_STACK,
|
||||
newStackCallback
|
||||
);
|
||||
eventTarget.addEventListener(EVENTS.STACK_VIEWPORT_NEW_STACK, newStackCallback);
|
||||
}
|
||||
|
||||
function elementDisabledHandler(evt) {
|
||||
@@ -271,15 +230,9 @@ export default async function init({
|
||||
// );
|
||||
}
|
||||
|
||||
eventTarget.addEventListener(
|
||||
EVENTS.ELEMENT_ENABLED,
|
||||
elementEnabledHandler.bind(null)
|
||||
);
|
||||
eventTarget.addEventListener(EVENTS.ELEMENT_ENABLED, elementEnabledHandler.bind(null));
|
||||
|
||||
eventTarget.addEventListener(
|
||||
EVENTS.ELEMENT_DISABLED,
|
||||
elementDisabledHandler.bind(null)
|
||||
);
|
||||
eventTarget.addEventListener(EVENTS.ELEMENT_DISABLED, elementDisabledHandler.bind(null));
|
||||
|
||||
viewportGridService.subscribe(
|
||||
viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED,
|
||||
@@ -292,8 +245,7 @@ export default async function init({
|
||||
|
||||
// check if reference lines are active
|
||||
const referenceLinesEnabled =
|
||||
toolGroup._toolInstances['ReferenceLines'].mode ===
|
||||
Enums.ToolModes.Enabled;
|
||||
toolGroup._toolInstances['ReferenceLines'].mode === Enums.ToolModes.Enabled;
|
||||
|
||||
if (!referenceLinesEnabled) {
|
||||
return;
|
||||
@@ -318,10 +270,9 @@ function CPUModal() {
|
||||
return (
|
||||
<div>
|
||||
<p>
|
||||
Your computer does not have enough GPU power to support the default GPU
|
||||
rendering mode. OHIF has switched to CPU rendering mode. Please note
|
||||
that CPU rendering does not support all features such as Volume
|
||||
Rendering, Multiplanar Reconstruction, and Segmentation Overlays.
|
||||
Your computer does not have enough GPU power to support the default GPU rendering mode. OHIF
|
||||
has switched to CPU rendering mode. Please note that CPU rendering does not support all
|
||||
features such as Volume Rendering, Multiplanar Reconstruction, and Segmentation Overlays.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -60,8 +60,7 @@ function initContextMenu({
|
||||
*/
|
||||
const cornerstoneViewportHandleEvent = (name, evt) => {
|
||||
const customizations =
|
||||
customizationService.get('cornerstoneViewportClickCommands') ||
|
||||
DEFAULT_CONTEXT_MENU_CLICKS;
|
||||
customizationService.get('cornerstoneViewportClickCommands') || DEFAULT_CONTEXT_MENU_CLICKS;
|
||||
const toRun = customizations[name];
|
||||
const options = {
|
||||
nearbyToolData: findNearbyToolData(commandsManager, evt),
|
||||
@@ -84,30 +83,18 @@ function initContextMenu({
|
||||
// TODO check update upstream
|
||||
setEnabledElement(viewportId, element);
|
||||
|
||||
element.addEventListener(
|
||||
cs3DToolsEvents.MOUSE_CLICK,
|
||||
cornerstoneViewportHandleClick
|
||||
);
|
||||
element.addEventListener(cs3DToolsEvents.MOUSE_CLICK, cornerstoneViewportHandleClick);
|
||||
}
|
||||
|
||||
function elementDisabledHandler(evt) {
|
||||
const { element } = evt.detail;
|
||||
|
||||
element.removeEventListener(
|
||||
cs3DToolsEvents.MOUSE_CLICK,
|
||||
cornerstoneViewportHandleClick
|
||||
);
|
||||
element.removeEventListener(cs3DToolsEvents.MOUSE_CLICK, cornerstoneViewportHandleClick);
|
||||
}
|
||||
|
||||
eventTarget.addEventListener(
|
||||
EVENTS.ELEMENT_ENABLED,
|
||||
elementEnabledHandler.bind(null)
|
||||
);
|
||||
eventTarget.addEventListener(EVENTS.ELEMENT_ENABLED, elementEnabledHandler.bind(null));
|
||||
|
||||
eventTarget.addEventListener(
|
||||
EVENTS.ELEMENT_DISABLED,
|
||||
elementDisabledHandler.bind(null)
|
||||
);
|
||||
eventTarget.addEventListener(EVENTS.ELEMENT_DISABLED, elementDisabledHandler.bind(null));
|
||||
}
|
||||
|
||||
export default initContextMenu;
|
||||
@@ -39,10 +39,7 @@ export type initDoubleClickArgs = {
|
||||
commandsManager: CommandsManager;
|
||||
};
|
||||
|
||||
function initDoubleClick({
|
||||
customizationService,
|
||||
commandsManager,
|
||||
}: initDoubleClickArgs): void {
|
||||
function initDoubleClick({ customizationService, commandsManager }: initDoubleClickArgs): void {
|
||||
const cornerstoneViewportHandleDoubleClick = (evt: CustomEvent) => {
|
||||
// Do not allow double click on a tool.
|
||||
const nearbyToolData = findNearbyToolData(commandsManager, evt);
|
||||
@@ -54,8 +51,7 @@ function initDoubleClick({
|
||||
|
||||
// Allows for the customization of the double click on a viewport.
|
||||
const customizations =
|
||||
customizationService.get('cornerstoneViewportClickCommands') ||
|
||||
DEFAULT_DOUBLE_CLICK;
|
||||
customizationService.get('cornerstoneViewportClickCommands') || DEFAULT_DOUBLE_CLICK;
|
||||
|
||||
const toRun = customizations[eventName];
|
||||
|
||||
@@ -84,15 +80,9 @@ function initDoubleClick({
|
||||
);
|
||||
}
|
||||
|
||||
eventTarget.addEventListener(
|
||||
EVENTS.ELEMENT_ENABLED,
|
||||
elementEnabledHandler.bind(null)
|
||||
);
|
||||
eventTarget.addEventListener(EVENTS.ELEMENT_ENABLED, elementEnabledHandler.bind(null));
|
||||
|
||||
eventTarget.addEventListener(
|
||||
EVENTS.ELEMENT_DISABLED,
|
||||
elementDisabledHandler.bind(null)
|
||||
);
|
||||
eventTarget.addEventListener(EVENTS.ELEMENT_DISABLED, elementDisabledHandler.bind(null));
|
||||
}
|
||||
|
||||
export default initDoubleClick;
|
||||
@@ -127,11 +127,8 @@ const initMeasurementService = (
|
||||
};
|
||||
|
||||
const connectToolsToMeasurementService = servicesManager => {
|
||||
const {
|
||||
measurementService,
|
||||
displaySetService,
|
||||
cornerstoneViewportService,
|
||||
} = servicesManager.services;
|
||||
const { measurementService, displaySetService, cornerstoneViewportService } =
|
||||
servicesManager.services;
|
||||
const csTools3DVer1MeasurementSource = initMeasurementService(
|
||||
measurementService,
|
||||
displaySetService,
|
||||
@@ -153,10 +150,7 @@ const connectToolsToMeasurementService = servicesManager => {
|
||||
} = annotationAddedEventDetail;
|
||||
const { toolName } = metadata;
|
||||
|
||||
if (
|
||||
csToolsEvent.type === completedEvt &&
|
||||
toolName === toolNames.CalibrationLine
|
||||
) {
|
||||
if (csToolsEvent.type === completedEvt && toolName === toolNames.CalibrationLine) {
|
||||
// show modal to input the measurement (mm)
|
||||
onCompletedCalibrationLine(servicesManager, csToolsEvent)
|
||||
.then(
|
||||
@@ -212,10 +206,8 @@ const connectToolsToMeasurementService = servicesManager => {
|
||||
try {
|
||||
const annotationSelectionEventDetail = csToolsEvent.detail;
|
||||
|
||||
const {
|
||||
added: addedSelectedAnnotationUIDs,
|
||||
removed: removedSelectedAnnotationUIDs,
|
||||
} = annotationSelectionEventDetail;
|
||||
const { added: addedSelectedAnnotationUIDs, removed: removedSelectedAnnotationUIDs } =
|
||||
annotationSelectionEventDetail;
|
||||
|
||||
if (removedSelectedAnnotationUIDs) {
|
||||
removedSelectedAnnotationUIDs.forEach(annotationUID =>
|
||||
@@ -283,12 +275,8 @@ const connectMeasurementServiceToTools = (
|
||||
cornerstoneViewportService,
|
||||
measurementSource
|
||||
) => {
|
||||
const {
|
||||
MEASUREMENT_REMOVED,
|
||||
MEASUREMENTS_CLEARED,
|
||||
MEASUREMENT_UPDATED,
|
||||
RAW_MEASUREMENT_ADDED,
|
||||
} = measurementService.EVENTS;
|
||||
const { MEASUREMENT_REMOVED, MEASUREMENTS_CLEARED, MEASUREMENT_UPDATED, RAW_MEASUREMENT_ADDED } =
|
||||
measurementService.EVENTS;
|
||||
|
||||
const csTools3DVer1MeasurementSource = measurementService.getSource(
|
||||
CORNERSTONE_3D_TOOLS_SOURCE_NAME,
|
||||
@@ -351,11 +339,7 @@ const connectMeasurementServiceToTools = (
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
referenceSeriesUID,
|
||||
referenceStudyUID,
|
||||
SOPInstanceUID,
|
||||
} = measurement;
|
||||
const { referenceSeriesUID, referenceStudyUID, SOPInstanceUID } = measurement;
|
||||
|
||||
const instance = DicomMetadataStore.getInstance(
|
||||
referenceStudyUID,
|
||||
@@ -368,9 +352,7 @@ const connectMeasurementServiceToTools = (
|
||||
|
||||
if (measurement?.metadata?.referencedImageId) {
|
||||
imageId = measurement.metadata.referencedImageId;
|
||||
frameNumber = getSOPInstanceAttributes(
|
||||
measurement.metadata.referencedImageId
|
||||
).frameNumber;
|
||||
frameNumber = getSOPInstanceAttributes(measurement.metadata.referencedImageId).frameNumber;
|
||||
} else {
|
||||
imageId = dataSource.getImageIdsForInstance({ instance });
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import * as cornerstone from '@cornerstonejs/core';
|
||||
import { volumeLoader } from '@cornerstonejs/core';
|
||||
import { cornerstoneStreamingImageVolumeLoader } from '@cornerstonejs/streaming-image-volume-loader';
|
||||
import dicomImageLoader, {
|
||||
webWorkerManager,
|
||||
} from '@cornerstonejs/dicom-image-loader';
|
||||
import dicomImageLoader, { webWorkerManager } from '@cornerstonejs/dicom-image-loader';
|
||||
import dicomParser from 'dicom-parser';
|
||||
import { errorHandler, utils } from '@ohif/core';
|
||||
|
||||
@@ -41,10 +39,7 @@ export default function initWADOImageLoader(
|
||||
dicomImageLoader.external.cornerstone = cornerstone;
|
||||
dicomImageLoader.external.dicomParser = dicomParser;
|
||||
|
||||
registerVolumeLoader(
|
||||
'cornerstoneStreamingImageVolume',
|
||||
cornerstoneStreamingImageVolumeLoader
|
||||
);
|
||||
registerVolumeLoader('cornerstoneStreamingImageVolume', cornerstoneStreamingImageVolumeLoader);
|
||||
|
||||
dicomImageLoader.configure({
|
||||
decodeConfig: {
|
||||
@@ -55,10 +50,9 @@ export default function initWADOImageLoader(
|
||||
// we should set this flag to false.
|
||||
convertFloatPixelDataToInt: false,
|
||||
},
|
||||
beforeSend: function(xhr) {
|
||||
beforeSend: function (xhr) {
|
||||
//TODO should be removed in the future and request emitted by DicomWebDataSource
|
||||
const sourceConfig =
|
||||
extensionManager.getActiveDataSource()?.[0].getConfig() ?? {};
|
||||
const sourceConfig = extensionManager.getActiveDataSource()?.[0].getConfig() ?? {};
|
||||
const headers = userAuthenticationService.getAuthorizationHeader();
|
||||
const acceptHeader = utils.generateAcceptHeader(
|
||||
sourceConfig.acceptHeader,
|
||||
|
||||
+11
-43
@@ -1,16 +1,8 @@
|
||||
import { ServicesManager, Types } from '@ohif/core';
|
||||
import {
|
||||
cache as cs3DCache,
|
||||
Enums,
|
||||
volumeLoader,
|
||||
utilities as utils,
|
||||
} from '@cornerstonejs/core';
|
||||
import { cache as cs3DCache, Enums, volumeLoader, utilities as utils } from '@cornerstonejs/core';
|
||||
|
||||
import getCornerstoneViewportType from '../../utils/getCornerstoneViewportType';
|
||||
import {
|
||||
StackViewportData,
|
||||
VolumeViewportData,
|
||||
} from '../../types/CornerstoneCacheService';
|
||||
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
|
||||
|
||||
const VOLUME_LOADER_SCHEME = 'cornerstoneStreamingImageVolume';
|
||||
|
||||
@@ -18,9 +10,7 @@ class CornerstoneCacheService {
|
||||
static REGISTRATION = {
|
||||
name: 'cornerstoneCacheService',
|
||||
altName: 'CornerstoneCacheService',
|
||||
create: ({
|
||||
servicesManager,
|
||||
}: Types.Extensions.ExtensionParams): CornerstoneCacheService => {
|
||||
create: ({ servicesManager }: Types.Extensions.ExtensionParams): CornerstoneCacheService => {
|
||||
return new CornerstoneCacheService(servicesManager);
|
||||
},
|
||||
};
|
||||
@@ -77,11 +67,7 @@ class CornerstoneCacheService {
|
||||
cs3DViewportType === Enums.ViewportType.ORTHOGRAPHIC ||
|
||||
cs3DViewportType === Enums.ViewportType.VOLUME_3D
|
||||
) {
|
||||
viewportData = await this._getVolumeViewportData(
|
||||
dataSource,
|
||||
displaySets,
|
||||
cs3DViewportType
|
||||
);
|
||||
viewportData = await this._getVolumeViewportData(dataSource, displaySets, cs3DViewportType);
|
||||
}
|
||||
|
||||
viewportData.viewportType = cs3DViewportType;
|
||||
@@ -134,20 +120,14 @@ class CornerstoneCacheService {
|
||||
// For Stack Viewport we don't have fusion currently
|
||||
const displaySet = displaySets[0];
|
||||
|
||||
let stackImageIds = this.stackImageIds.get(
|
||||
displaySet.displaySetInstanceUID
|
||||
);
|
||||
let stackImageIds = this.stackImageIds.get(displaySet.displaySetInstanceUID);
|
||||
|
||||
if (!stackImageIds) {
|
||||
stackImageIds = this._getCornerstoneStackImageIds(displaySet, dataSource);
|
||||
this.stackImageIds.set(displaySet.displaySetInstanceUID, stackImageIds);
|
||||
}
|
||||
|
||||
const {
|
||||
displaySetInstanceUID,
|
||||
StudyInstanceUID,
|
||||
isCompositeStack,
|
||||
} = displaySet;
|
||||
const { displaySetInstanceUID, StudyInstanceUID, isCompositeStack } = displaySet;
|
||||
|
||||
const StackViewportData: StackViewportData = {
|
||||
viewportType,
|
||||
@@ -196,31 +176,22 @@ class CornerstoneCacheService {
|
||||
continue;
|
||||
}
|
||||
|
||||
const volumeLoaderSchema =
|
||||
displaySet.volumeLoaderSchema ?? VOLUME_LOADER_SCHEME;
|
||||
const volumeLoaderSchema = displaySet.volumeLoaderSchema ?? VOLUME_LOADER_SCHEME;
|
||||
|
||||
const volumeId = `${volumeLoaderSchema}:${displaySet.displaySetInstanceUID}`;
|
||||
|
||||
let volumeImageIds = this.volumeImageIds.get(
|
||||
displaySet.displaySetInstanceUID
|
||||
);
|
||||
let volumeImageIds = this.volumeImageIds.get(displaySet.displaySetInstanceUID);
|
||||
|
||||
let volume = cs3DCache.getVolume(volumeId);
|
||||
|
||||
if (!volumeImageIds || !volume) {
|
||||
volumeImageIds = this._getCornerstoneVolumeImageIds(
|
||||
displaySet,
|
||||
dataSource
|
||||
);
|
||||
volumeImageIds = this._getCornerstoneVolumeImageIds(displaySet, dataSource);
|
||||
|
||||
volume = await volumeLoader.createAndCacheVolume(volumeId, {
|
||||
imageIds: volumeImageIds,
|
||||
});
|
||||
|
||||
this.volumeImageIds.set(
|
||||
displaySet.displaySetInstanceUID,
|
||||
volumeImageIds
|
||||
);
|
||||
this.volumeImageIds.set(displaySet.displaySetInstanceUID, volumeImageIds);
|
||||
}
|
||||
|
||||
volumeData.push({
|
||||
@@ -268,10 +239,7 @@ class CornerstoneCacheService {
|
||||
}
|
||||
|
||||
private _getCornerstoneVolumeImageIds(displaySet, dataSource): string[] {
|
||||
const stackImageIds = this._getCornerstoneStackImageIds(
|
||||
displaySet,
|
||||
dataSource
|
||||
);
|
||||
const stackImageIds = this._getCornerstoneStackImageIds(displaySet, dataSource);
|
||||
|
||||
return stackImageIds;
|
||||
}
|
||||
|
||||
+19
-24
@@ -7,32 +7,27 @@
|
||||
* @returns An array of object that includes data, id, segmentIndex, color
|
||||
* and geometry Id
|
||||
*/
|
||||
export function mapROIContoursToRTStructData(
|
||||
structureSet: unknown,
|
||||
rtDisplaySetUID: unknown
|
||||
) {
|
||||
return structureSet.ROIContours.map(
|
||||
({ contourPoints, ROINumber, ROIName, colorArray }) => {
|
||||
const data = contourPoints.map(({ points, ...rest }) => {
|
||||
const newPoints = points.map(({ x, y, z }) => {
|
||||
return [x, y, z];
|
||||
});
|
||||
|
||||
return {
|
||||
...rest,
|
||||
points: newPoints,
|
||||
};
|
||||
export function mapROIContoursToRTStructData(structureSet: unknown, rtDisplaySetUID: unknown) {
|
||||
return structureSet.ROIContours.map(({ contourPoints, ROINumber, ROIName, colorArray }) => {
|
||||
const data = contourPoints.map(({ points, ...rest }) => {
|
||||
const newPoints = points.map(({ x, y, z }) => {
|
||||
return [x, y, z];
|
||||
});
|
||||
|
||||
const id = ROIName || ROINumber;
|
||||
|
||||
return {
|
||||
data,
|
||||
id,
|
||||
segmentIndex: ROINumber,
|
||||
color: colorArray,
|
||||
geometryId: `${rtDisplaySetUID}:${id}:segmentIndex-${ROINumber}`,
|
||||
...rest,
|
||||
points: newPoints,
|
||||
};
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const id = ROIName || ROINumber;
|
||||
|
||||
return {
|
||||
data,
|
||||
id,
|
||||
segmentIndex: ROINumber,
|
||||
color: colorArray,
|
||||
geometryId: `${rtDisplaySetUID}:${id}:segmentIndex-${ROINumber}`,
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -21,11 +21,7 @@ import {
|
||||
import isEqual from 'lodash.isequal';
|
||||
import { Types as ohifTypes } from '@ohif/core';
|
||||
import { easeInOutBell, reverseEaseInOutBell } from '../../utils/transitions';
|
||||
import {
|
||||
Segment,
|
||||
Segmentation,
|
||||
SegmentationConfig,
|
||||
} from './SegmentationServiceTypes';
|
||||
import { Segment, Segmentation, SegmentationConfig } from './SegmentationServiceTypes';
|
||||
import { mapROIContoursToRTStructData } from './RTSTRUCT/mapROIContoursToRTStructData';
|
||||
|
||||
const { COLOR_LUT } = cstConstants;
|
||||
@@ -42,8 +38,7 @@ const EVENTS = {
|
||||
// fired when the segmentation is removed
|
||||
SEGMENTATION_REMOVED: 'event::segmentation_removed',
|
||||
// fired when the configuration for the segmentation is changed (e.g., brush size, render fill, outline thickness, etc.)
|
||||
SEGMENTATION_CONFIGURATION_CHANGED:
|
||||
'event::segmentation_configuration_changed',
|
||||
SEGMENTATION_CONFIGURATION_CHANGED: 'event::segmentation_configuration_changed',
|
||||
// fired when the active segment is loaded in SEG or RTSTRUCT
|
||||
SEGMENT_LOADING_COMPLETE: 'event::segment_loading_complete',
|
||||
// for all segments
|
||||
@@ -64,9 +59,7 @@ class SegmentationService extends PubSubService {
|
||||
static REGISTRATION = {
|
||||
name: 'segmentationService',
|
||||
altName: 'SegmentationService',
|
||||
create: ({
|
||||
servicesManager,
|
||||
}: OhifTypes.Extensions.ExtensionParams): SegmentationService => {
|
||||
create: ({ servicesManager }: OhifTypes.Extensions.ExtensionParams): SegmentationService => {
|
||||
return new SegmentationService({ servicesManager });
|
||||
},
|
||||
};
|
||||
@@ -138,10 +131,10 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
|
||||
|
||||
const {
|
||||
segmentationRepresentationUID,
|
||||
segmentation,
|
||||
} = this._getSegmentationInfo(segmentationId, toolGroupId);
|
||||
const { segmentationRepresentationUID, segmentation } = this._getSegmentationInfo(
|
||||
segmentationId,
|
||||
toolGroupId
|
||||
);
|
||||
|
||||
if (this._getSegmentInfo(segmentation, segmentIndex)) {
|
||||
throw new Error(`Segment ${segmentIndex} already exists`);
|
||||
@@ -166,32 +159,14 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
const suppressEvents = true;
|
||||
if (properties !== undefined) {
|
||||
const {
|
||||
color: newColor,
|
||||
opacity,
|
||||
isLocked,
|
||||
visibility,
|
||||
active,
|
||||
} = properties;
|
||||
const { color: newColor, opacity, isLocked, visibility, active } = properties;
|
||||
|
||||
if (newColor !== undefined) {
|
||||
this._setSegmentColor(
|
||||
segmentationId,
|
||||
segmentIndex,
|
||||
newColor,
|
||||
toolGroupId,
|
||||
suppressEvents
|
||||
);
|
||||
this._setSegmentColor(segmentationId, segmentIndex, newColor, toolGroupId, suppressEvents);
|
||||
}
|
||||
|
||||
if (opacity !== undefined) {
|
||||
this._setSegmentOpacity(
|
||||
segmentationId,
|
||||
segmentIndex,
|
||||
opacity,
|
||||
toolGroupId,
|
||||
suppressEvents
|
||||
);
|
||||
this._setSegmentOpacity(segmentationId, segmentIndex, opacity, toolGroupId, suppressEvents);
|
||||
}
|
||||
|
||||
if (visibility !== undefined) {
|
||||
@@ -209,12 +184,7 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
|
||||
if (isLocked !== undefined) {
|
||||
this._setSegmentLocked(
|
||||
segmentationId,
|
||||
segmentIndex,
|
||||
isLocked,
|
||||
suppressEvents
|
||||
);
|
||||
this._setSegmentLocked(segmentationId, segmentIndex, isLocked, suppressEvents);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,9 +255,7 @@ class SegmentationService extends PubSubService {
|
||||
if (segmentation.activeSegmentIndex === segmentIndex) {
|
||||
const segmentIndices = Object.keys(segmentation.segments);
|
||||
|
||||
const newActiveSegmentIndex = segmentIndices.length
|
||||
? Number(segmentIndices[0])
|
||||
: 1;
|
||||
const newActiveSegmentIndex = segmentIndices.length ? Number(segmentIndices[0]) : 1;
|
||||
|
||||
this._setActiveSegment(segmentationId, newActiveSegmentIndex, true);
|
||||
}
|
||||
@@ -319,19 +287,10 @@ class SegmentationService extends PubSubService {
|
||||
isLocked: boolean
|
||||
): void {
|
||||
const suppressEvents = false;
|
||||
this._setSegmentLocked(
|
||||
segmentationId,
|
||||
segmentIndex,
|
||||
isLocked,
|
||||
suppressEvents
|
||||
);
|
||||
this._setSegmentLocked(segmentationId, segmentIndex, isLocked, suppressEvents);
|
||||
}
|
||||
|
||||
public setSegmentLabel(
|
||||
segmentationId: string,
|
||||
segmentIndex: number,
|
||||
segmentLabel: string
|
||||
): void {
|
||||
public setSegmentLabel(segmentationId: string, segmentIndex: number, segmentLabel: string): void {
|
||||
this._setSegmentLabel(segmentationId, segmentIndex, segmentLabel);
|
||||
}
|
||||
|
||||
@@ -387,24 +346,14 @@ class SegmentationService extends PubSubService {
|
||||
this._setSegmentOpacity(segmentationId, segmentIndex, opacity, toolGroupId);
|
||||
}
|
||||
|
||||
public setActiveSegmentationForToolGroup(
|
||||
segmentationId: string,
|
||||
toolGroupId?: string
|
||||
): void {
|
||||
public setActiveSegmentationForToolGroup(segmentationId: string, toolGroupId?: string): void {
|
||||
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
|
||||
|
||||
const suppressEvents = false;
|
||||
this._setActiveSegmentationForToolGroup(
|
||||
segmentationId,
|
||||
toolGroupId,
|
||||
suppressEvents
|
||||
);
|
||||
this._setActiveSegmentationForToolGroup(segmentationId, toolGroupId, suppressEvents);
|
||||
}
|
||||
|
||||
public setActiveSegmentForSegmentation(
|
||||
segmentationId: string,
|
||||
segmentIndex: number
|
||||
): void {
|
||||
public setActiveSegmentForSegmentation(segmentationId: string, segmentIndex: number): void {
|
||||
this._setActiveSegment(segmentationId, segmentIndex, false);
|
||||
}
|
||||
|
||||
@@ -420,9 +369,7 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
* @return Array of segmentations
|
||||
*/
|
||||
public getSegmentations(
|
||||
filterNonHydratedSegmentations = true
|
||||
): Segmentation[] {
|
||||
public getSegmentations(filterNonHydratedSegmentations = true): Segmentation[] {
|
||||
const segmentations = this._getSegmentations();
|
||||
|
||||
return (
|
||||
@@ -435,10 +382,7 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
private _getSegmentations(): Segmentation[] {
|
||||
const segmentations = this.arrayOfObjects(this.segmentations);
|
||||
return (
|
||||
segmentations &&
|
||||
segmentations.map(m => this.segmentations[Object.keys(m)[0]])
|
||||
);
|
||||
return segmentations && segmentations.map(m => this.segmentations[Object.keys(m)[0]]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -477,8 +421,7 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
|
||||
const representationType = segmentation.type;
|
||||
const representationData =
|
||||
segmentation.representationData[representationType];
|
||||
const representationData = segmentation.representationData[representationType];
|
||||
cstSegmentation.addSegmentations([
|
||||
{
|
||||
segmentationId,
|
||||
@@ -566,9 +509,7 @@ class SegmentationService extends PubSubService {
|
||||
const { labelmapBufferArray, referencedVolumeId } = segDisplaySet;
|
||||
|
||||
if (!labelmapBufferArray || !referencedVolumeId) {
|
||||
throw new Error(
|
||||
'No labelmapBufferArray or referencedVolumeId found for the SEG displaySet'
|
||||
);
|
||||
throw new Error('No labelmapBufferArray or referencedVolumeId found for the SEG displaySet');
|
||||
}
|
||||
|
||||
// if the labelmap doesn't exist, we need to create it first from the
|
||||
@@ -576,23 +517,18 @@ class SegmentationService extends PubSubService {
|
||||
const referencedVolume = cache.getVolume(referencedVolumeId);
|
||||
|
||||
if (!referencedVolume) {
|
||||
throw new Error(
|
||||
`No volume found for referencedVolumeId: ${referencedVolumeId}`
|
||||
);
|
||||
throw new Error(`No volume found for referencedVolumeId: ${referencedVolumeId}`);
|
||||
}
|
||||
|
||||
// Force use of a Uint8Array SharedArrayBuffer for the segmentation to save space and so
|
||||
// it is easily compressible in worker thread.
|
||||
const derivedVolume = await volumeLoader.createAndCacheDerivedVolume(
|
||||
referencedVolumeId,
|
||||
{
|
||||
volumeId: segmentationId,
|
||||
targetBuffer: {
|
||||
type: 'Uint8Array',
|
||||
sharedArrayBuffer: true,
|
||||
},
|
||||
}
|
||||
);
|
||||
const derivedVolume = await volumeLoader.createAndCacheDerivedVolume(referencedVolumeId, {
|
||||
volumeId: segmentationId,
|
||||
targetBuffer: {
|
||||
type: 'Uint8Array',
|
||||
sharedArrayBuffer: true,
|
||||
},
|
||||
});
|
||||
const derivedVolumeScalarData = derivedVolume.getScalarData();
|
||||
|
||||
const segmentsInfo = segDisplaySet.segMetadata.data;
|
||||
@@ -680,10 +616,7 @@ class SegmentationService extends PubSubService {
|
||||
const defaultScheme = this._getDefaultSegmentationScheme();
|
||||
const rtDisplaySetUID = rtDisplaySet.displaySetInstanceUID;
|
||||
|
||||
const allRTStructData = mapROIContoursToRTStructData(
|
||||
structureSet,
|
||||
rtDisplaySetUID
|
||||
);
|
||||
const allRTStructData = mapROIContoursToRTStructData(structureSet, rtDisplaySetUID);
|
||||
|
||||
// sort by segmentIndex
|
||||
allRTStructData.sort((a, b) => a.segmentIndex - b.segmentIndex);
|
||||
@@ -726,19 +659,16 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
// catch error instead of failing to allow loading to continue
|
||||
try {
|
||||
const geometry = await geometryLoader.createAndCacheGeometry(
|
||||
geometryId,
|
||||
{
|
||||
geometryData: {
|
||||
data,
|
||||
id,
|
||||
color,
|
||||
frameOfReferenceUID: structureSet.frameOfReferenceUID,
|
||||
segmentIndex,
|
||||
},
|
||||
type: csEnums.GeometryType.CONTOUR,
|
||||
}
|
||||
);
|
||||
const geometry = await geometryLoader.createAndCacheGeometry(geometryId, {
|
||||
geometryData: {
|
||||
data,
|
||||
id,
|
||||
color,
|
||||
frameOfReferenceUID: structureSet.frameOfReferenceUID,
|
||||
segmentIndex,
|
||||
},
|
||||
type: csEnums.GeometryType.CONTOUR,
|
||||
});
|
||||
|
||||
const contourSet = geometry.data;
|
||||
const centroid = contourSet.getCentroid();
|
||||
@@ -758,9 +688,7 @@ class SegmentationService extends PubSubService {
|
||||
const numInitialized = Object.keys(segmentsCachedStats).length;
|
||||
|
||||
// Calculate percentage completed
|
||||
const percentComplete = Math.round(
|
||||
(numInitialized / allRTStructData.length) * 100
|
||||
);
|
||||
const percentComplete = Math.round((numInitialized / allRTStructData.length) * 100);
|
||||
|
||||
this._broadcastEvent(EVENTS.SEGMENT_LOADING_COMPLETE, {
|
||||
percentComplete,
|
||||
@@ -824,8 +752,7 @@ class SegmentationService extends PubSubService {
|
||||
const { world } = center;
|
||||
|
||||
// todo: generalize
|
||||
toolGroupId =
|
||||
toolGroupId || this._getToolGroupIdsWithSegmentation(segmentationId);
|
||||
toolGroupId = toolGroupId || this._getToolGroupIdsWithSegmentation(segmentationId);
|
||||
|
||||
const toolGroups = [];
|
||||
|
||||
@@ -842,10 +769,7 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
// @ts-ignore
|
||||
for (const { viewportId, renderingEngineId } of viewportsInfo) {
|
||||
const { viewport } = getEnabledElementByIds(
|
||||
viewportId,
|
||||
renderingEngineId
|
||||
);
|
||||
const { viewport } = getEnabledElementByIds(viewportId, renderingEngineId);
|
||||
cstUtils.viewport.jumpToWorld(viewport, world);
|
||||
}
|
||||
|
||||
@@ -888,9 +812,7 @@ class SegmentationService extends PubSubService {
|
||||
const { segments } = segmentation;
|
||||
|
||||
const highlightFn =
|
||||
type === LABELMAP
|
||||
? this._highlightLabelmap.bind(this)
|
||||
: this._highlightContour.bind(this);
|
||||
type === LABELMAP ? this._highlightLabelmap.bind(this) : this._highlightContour.bind(this);
|
||||
|
||||
const adjustedAlpha = type === LABELMAP ? alpha : 1 - alpha;
|
||||
|
||||
@@ -914,9 +836,7 @@ class SegmentationService extends PubSubService {
|
||||
): Promise<string> => {
|
||||
const { displaySetService } = this.servicesManager.services;
|
||||
|
||||
const displaySet = displaySetService.getDisplaySetByUID(
|
||||
displaySetInstanceUID
|
||||
);
|
||||
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||
|
||||
// Todo: we currently only support labelmap for segmentation for a displaySet
|
||||
const representationType = LABELMAP;
|
||||
@@ -977,9 +897,7 @@ class SegmentationService extends PubSubService {
|
||||
const segmentation = this.getSegmentation(segmentationId);
|
||||
|
||||
if (!segmentation) {
|
||||
throw new Error(
|
||||
`Segmentation with segmentationId ${segmentationId} not found.`
|
||||
);
|
||||
throw new Error(`Segmentation with segmentationId ${segmentationId} not found.`);
|
||||
}
|
||||
|
||||
if (hydrateSegmentation) {
|
||||
@@ -1019,34 +937,16 @@ class SegmentationService extends PubSubService {
|
||||
continue;
|
||||
}
|
||||
|
||||
const {
|
||||
segmentIndex,
|
||||
color,
|
||||
isLocked,
|
||||
isVisible: visibility,
|
||||
opacity,
|
||||
} = segment;
|
||||
const { segmentIndex, color, isLocked, isVisible: visibility, opacity } = segment;
|
||||
|
||||
const suppressEvents = true;
|
||||
|
||||
if (color !== undefined) {
|
||||
this._setSegmentColor(
|
||||
segmentationId,
|
||||
segmentIndex,
|
||||
color,
|
||||
toolGroupId,
|
||||
suppressEvents
|
||||
);
|
||||
this._setSegmentColor(segmentationId, segmentIndex, color, toolGroupId, suppressEvents);
|
||||
}
|
||||
|
||||
if (opacity !== undefined) {
|
||||
this._setSegmentOpacity(
|
||||
segmentationId,
|
||||
segmentIndex,
|
||||
opacity,
|
||||
toolGroupId,
|
||||
suppressEvents
|
||||
);
|
||||
this._setSegmentOpacity(segmentationId, segmentIndex, opacity, toolGroupId, suppressEvents);
|
||||
}
|
||||
|
||||
if (visibility !== undefined) {
|
||||
@@ -1060,12 +960,7 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
|
||||
if (isLocked !== undefined) {
|
||||
this._setSegmentLocked(
|
||||
segmentationId,
|
||||
segmentIndex,
|
||||
isLocked,
|
||||
suppressEvents
|
||||
);
|
||||
this._setSegmentLocked(segmentationId, segmentIndex, isLocked, suppressEvents);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1102,25 +997,16 @@ class SegmentationService extends PubSubService {
|
||||
});
|
||||
};
|
||||
|
||||
public getToolGroupIdsWithSegmentation = (
|
||||
segmentationId: string
|
||||
): string[] => {
|
||||
const toolGroupIds = cstSegmentation.state.getToolGroupIdsWithSegmentation(
|
||||
segmentationId
|
||||
);
|
||||
public getToolGroupIdsWithSegmentation = (segmentationId: string): string[] => {
|
||||
const toolGroupIds = cstSegmentation.state.getToolGroupIdsWithSegmentation(segmentationId);
|
||||
return toolGroupIds;
|
||||
};
|
||||
|
||||
public hydrateSegmentation = (
|
||||
segmentationId: string,
|
||||
suppressEvents = false
|
||||
): void => {
|
||||
public hydrateSegmentation = (segmentationId: string, suppressEvents = false): void => {
|
||||
const segmentation = this.getSegmentation(segmentationId);
|
||||
|
||||
if (!segmentation) {
|
||||
throw new Error(
|
||||
`Segmentation with segmentationId ${segmentationId} not found.`
|
||||
);
|
||||
throw new Error(`Segmentation with segmentationId ${segmentationId} not found.`);
|
||||
}
|
||||
|
||||
this._setDisplaySetIsHydrated(segmentationId, true);
|
||||
@@ -1134,13 +1020,8 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
};
|
||||
|
||||
private _setDisplaySetIsHydrated(
|
||||
displaySetUID: string,
|
||||
isHydrated: boolean
|
||||
): void {
|
||||
const {
|
||||
DisplaySetService: displaySetService,
|
||||
} = this.servicesManager.services;
|
||||
private _setDisplaySetIsHydrated(displaySetUID: string, isHydrated: boolean): void {
|
||||
const { DisplaySetService: displaySetService } = this.servicesManager.services;
|
||||
const displaySet = displaySetService.getDisplaySetByUID(displaySetUID);
|
||||
displaySet.isHydrated = isHydrated;
|
||||
displaySetService.setDisplaySetMetadataInvalidated(displaySetUID, false);
|
||||
@@ -1259,17 +1140,13 @@ class SegmentationService extends PubSubService {
|
||||
): void {
|
||||
const uids = segmentationRepresentationUIDsIds || [];
|
||||
if (!uids.length) {
|
||||
const representations = cstSegmentation.state.getSegmentationRepresentations(
|
||||
toolGroupId
|
||||
);
|
||||
const representations = cstSegmentation.state.getSegmentationRepresentations(toolGroupId);
|
||||
|
||||
if (!representations || !representations.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
uids.push(
|
||||
...representations.map(rep => rep.segmentationRepresentationUID)
|
||||
);
|
||||
uids.push(...representations.map(rep => rep.segmentationRepresentationUID));
|
||||
}
|
||||
|
||||
cstSegmentation.removeSegmentationsFromToolGroup(toolGroupId, uids);
|
||||
@@ -1285,9 +1162,7 @@ class SegmentationService extends PubSubService {
|
||||
const wasActive = segmentation.isActive;
|
||||
|
||||
if (!segmentationId || !segmentation) {
|
||||
console.warn(
|
||||
`No segmentationId provided, or unable to find segmentation by id.`
|
||||
);
|
||||
console.warn(`No segmentationId provided, or unable to find segmentation by id.`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1309,11 +1184,7 @@ class SegmentationService extends PubSubService {
|
||||
if (remainingSegmentations.length) {
|
||||
const { id } = remainingSegmentations[0];
|
||||
|
||||
this._setActiveSegmentationForToolGroup(
|
||||
id,
|
||||
this._getFirstToolGroupId(),
|
||||
false
|
||||
);
|
||||
this._setActiveSegmentationForToolGroup(id, this._getFirstToolGroupId(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1337,9 +1208,8 @@ class SegmentationService extends PubSubService {
|
||||
// toolGroupId
|
||||
// );
|
||||
|
||||
const segmentationRepresentations = this.getSegmentationRepresentationsForToolGroup(
|
||||
toolGroupId
|
||||
);
|
||||
const segmentationRepresentations =
|
||||
this.getSegmentationRepresentationsForToolGroup(toolGroupId);
|
||||
|
||||
const typeToUse = segmentationRepresentations?.[0]?.type || LABELMAP;
|
||||
|
||||
@@ -1397,11 +1267,7 @@ class SegmentationService extends PubSubService {
|
||||
setConfigValueIfDefined('outlineOpacity', outlineOpacity, v => v / 100);
|
||||
setConfigValueIfDefined('fillAlpha', fillAlpha, v => v / 100);
|
||||
setConfigValueIfDefined('renderFill', renderFill);
|
||||
setConfigValueIfDefined(
|
||||
'fillAlphaInactive',
|
||||
fillAlphaInactive,
|
||||
v => v / 100
|
||||
);
|
||||
setConfigValueIfDefined('fillAlphaInactive', fillAlphaInactive, v => v / 100);
|
||||
setConfigValueIfDefined('outlineOpacityInactive', fillAlphaInactive, v =>
|
||||
Math.max(0.75, v / 100)
|
||||
);
|
||||
@@ -1435,10 +1301,7 @@ class SegmentationService extends PubSubService {
|
||||
// });
|
||||
// }
|
||||
|
||||
this._broadcastEvent(
|
||||
this.EVENTS.SEGMENTATION_CONFIGURATION_CHANGED,
|
||||
this.getConfiguration()
|
||||
);
|
||||
this._broadcastEvent(this.EVENTS.SEGMENTATION_CONFIGURATION_CHANGED, this.getConfiguration());
|
||||
};
|
||||
|
||||
public getLabelmapVolume = (segmentationId: string) => {
|
||||
@@ -1472,9 +1335,7 @@ class SegmentationService extends PubSubService {
|
||||
const segmentInfo = segmentation.segments[segmentIndex];
|
||||
|
||||
if (segmentInfo === undefined) {
|
||||
throw new Error(
|
||||
`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`
|
||||
);
|
||||
throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);
|
||||
}
|
||||
|
||||
segmentInfo.label = label;
|
||||
@@ -1487,14 +1348,8 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
}
|
||||
|
||||
public shouldRenderSegmentation(
|
||||
viewportDisplaySetInstanceUIDs,
|
||||
segDisplaySetInstanceUID
|
||||
) {
|
||||
if (
|
||||
!viewportDisplaySetInstanceUIDs ||
|
||||
!viewportDisplaySetInstanceUIDs.length
|
||||
) {
|
||||
public shouldRenderSegmentation(viewportDisplaySetInstanceUIDs, segDisplaySetInstanceUID) {
|
||||
if (!viewportDisplaySetInstanceUIDs || !viewportDisplaySetInstanceUIDs.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1502,20 +1357,14 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
let shouldDisplaySeg = false;
|
||||
|
||||
const segDisplaySet = displaySetService.getDisplaySetByUID(
|
||||
segDisplaySetInstanceUID
|
||||
);
|
||||
const segDisplaySet = displaySetService.getDisplaySetByUID(segDisplaySetInstanceUID);
|
||||
|
||||
const segFrameOfReferenceUID = this._getFrameOfReferenceUIDForSeg(
|
||||
segDisplaySet
|
||||
);
|
||||
const segFrameOfReferenceUID = this._getFrameOfReferenceUIDForSeg(segDisplaySet);
|
||||
|
||||
// check if the displaySet is sharing the same frameOfReferenceUID
|
||||
// with the new segmentation
|
||||
for (const displaySetInstanceUID of viewportDisplaySetInstanceUIDs) {
|
||||
const displaySet = displaySetService.getDisplaySetByUID(
|
||||
displaySetInstanceUID
|
||||
);
|
||||
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||
|
||||
// Todo: this might not be ideal for use cases such as 4D, since we
|
||||
// don't want to show the segmentation for all the frames
|
||||
@@ -1563,10 +1412,7 @@ class SegmentationService extends PubSubService {
|
||||
segmentation.isActive = segmentation.id === segmentationId;
|
||||
});
|
||||
|
||||
const representation = this._getSegmentationRepresentation(
|
||||
segmentationId,
|
||||
toolGroupId
|
||||
);
|
||||
const representation = this._getSegmentationRepresentation(segmentationId, toolGroupId);
|
||||
|
||||
cstSegmentation.activeSegmentation.setActiveSegmentationRepresentation(
|
||||
toolGroupId,
|
||||
@@ -1580,16 +1426,11 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
}
|
||||
|
||||
private _toggleSegmentationVisibility = (
|
||||
segmentationId: string,
|
||||
suppressEvents = false
|
||||
) => {
|
||||
private _toggleSegmentationVisibility = (segmentationId: string, suppressEvents = false) => {
|
||||
const segmentation = this.segmentations[segmentationId];
|
||||
|
||||
if (!segmentation) {
|
||||
throw new Error(
|
||||
`Segmentation with segmentationId ${segmentationId} not found.`
|
||||
);
|
||||
throw new Error(`Segmentation with segmentationId ${segmentationId} not found.`);
|
||||
}
|
||||
|
||||
segmentation.isVisible = !segmentation.isVisible;
|
||||
@@ -1603,21 +1444,14 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
};
|
||||
|
||||
private _setActiveSegment(
|
||||
segmentationId: string,
|
||||
segmentIndex: number,
|
||||
suppressEvents = false
|
||||
) {
|
||||
private _setActiveSegment(segmentationId: string, segmentIndex: number, suppressEvents = false) {
|
||||
const segmentation = this.getSegmentation(segmentationId);
|
||||
|
||||
if (segmentation === undefined) {
|
||||
throw new Error(`no segmentation for segmentationId: ${segmentationId}`);
|
||||
}
|
||||
|
||||
cstSegmentation.segmentIndex.setActiveSegmentIndex(
|
||||
segmentationId,
|
||||
segmentIndex
|
||||
);
|
||||
cstSegmentation.segmentIndex.setActiveSegmentIndex(segmentationId, segmentIndex);
|
||||
|
||||
segmentation.activeSegmentIndex = segmentIndex;
|
||||
|
||||
@@ -1641,8 +1475,7 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
|
||||
private _getVolumeIdForDisplaySet(displaySet) {
|
||||
const volumeLoaderSchema =
|
||||
displaySet.volumeLoaderSchema ?? VOLUME_LOADER_SCHEME;
|
||||
const volumeLoaderSchema = displaySet.volumeLoaderSchema ?? VOLUME_LOADER_SCHEME;
|
||||
|
||||
return `${volumeLoaderSchema}:${displaySet.displaySetInstanceUID}`;
|
||||
}
|
||||
@@ -1663,9 +1496,7 @@ class SegmentationService extends PubSubService {
|
||||
const segmentInfo = this._getSegmentInfo(segmentation, segmentIndex);
|
||||
|
||||
if (segmentInfo === undefined) {
|
||||
throw new Error(
|
||||
`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`
|
||||
);
|
||||
throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);
|
||||
}
|
||||
|
||||
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
|
||||
@@ -1676,9 +1507,7 @@ class SegmentationService extends PubSubService {
|
||||
);
|
||||
|
||||
if (!segmentationRepresentation) {
|
||||
throw new Error(
|
||||
'Must add representation to toolgroup before setting segments'
|
||||
);
|
||||
throw new Error('Must add representation to toolgroup before setting segments');
|
||||
}
|
||||
const { segmentationRepresentationUID } = segmentationRepresentation;
|
||||
|
||||
@@ -1743,18 +1572,12 @@ class SegmentationService extends PubSubService {
|
||||
const segmentInfo = this._getSegmentInfo(segmentation, segmentIndex);
|
||||
|
||||
if (segmentInfo === undefined) {
|
||||
throw new Error(
|
||||
`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`
|
||||
);
|
||||
throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);
|
||||
}
|
||||
|
||||
segmentInfo.isLocked = isLocked;
|
||||
|
||||
cstSegmentation.segmentLocking.setSegmentIndexLocked(
|
||||
segmentationId,
|
||||
segmentIndex,
|
||||
isLocked
|
||||
);
|
||||
cstSegmentation.segmentLocking.setSegmentIndexLocked(segmentationId, segmentIndex, isLocked);
|
||||
|
||||
if (suppressEvents === false) {
|
||||
this._broadcastEvent(this.EVENTS.SEGMENTATION_UPDATED, {
|
||||
@@ -1772,10 +1595,10 @@ class SegmentationService extends PubSubService {
|
||||
) {
|
||||
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
|
||||
|
||||
const {
|
||||
segmentationRepresentationUID,
|
||||
segmentation,
|
||||
} = this._getSegmentationInfo(segmentationId, toolGroupId);
|
||||
const { segmentationRepresentationUID, segmentation } = this._getSegmentationInfo(
|
||||
segmentationId,
|
||||
toolGroupId
|
||||
);
|
||||
|
||||
if (segmentation === undefined) {
|
||||
throw new Error(`no segmentation for segmentationId: ${segmentationId}`);
|
||||
@@ -1784,9 +1607,7 @@ class SegmentationService extends PubSubService {
|
||||
const segmentInfo = this._getSegmentInfo(segmentation, segmentIndex);
|
||||
|
||||
if (segmentInfo === undefined) {
|
||||
throw new Error(
|
||||
`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`
|
||||
);
|
||||
throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);
|
||||
}
|
||||
|
||||
segmentInfo.isVisible = isVisible;
|
||||
@@ -1828,9 +1649,7 @@ class SegmentationService extends PubSubService {
|
||||
const segmentInfo = this._getSegmentInfo(segmentation, segmentIndex);
|
||||
|
||||
if (segmentInfo === undefined) {
|
||||
throw new Error(
|
||||
`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`
|
||||
);
|
||||
throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);
|
||||
}
|
||||
|
||||
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
|
||||
@@ -1841,9 +1660,7 @@ class SegmentationService extends PubSubService {
|
||||
);
|
||||
|
||||
if (!segmentationRepresentation) {
|
||||
throw new Error(
|
||||
'Must add representation to toolgroup before setting segments'
|
||||
);
|
||||
throw new Error('Must add representation to toolgroup before setting segments');
|
||||
}
|
||||
const { segmentationRepresentationUID } = segmentationRepresentation;
|
||||
|
||||
@@ -1884,9 +1701,7 @@ class SegmentationService extends PubSubService {
|
||||
const segmentInfo = this._getSegmentInfo(segmentation, segmentIndex);
|
||||
|
||||
if (segmentInfo === undefined) {
|
||||
throw new Error(
|
||||
`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`
|
||||
);
|
||||
throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);
|
||||
}
|
||||
|
||||
segmentInfo.label = segmentLabel;
|
||||
@@ -1899,9 +1714,8 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
|
||||
private _getSegmentationRepresentation(segmentationId, toolGroupId) {
|
||||
const segmentationRepresentations = this.getSegmentationRepresentationsForToolGroup(
|
||||
toolGroupId
|
||||
);
|
||||
const segmentationRepresentations =
|
||||
this.getSegmentationRepresentationsForToolGroup(toolGroupId);
|
||||
|
||||
if (segmentationRepresentations.length === 0) {
|
||||
return;
|
||||
@@ -1974,21 +1788,13 @@ class SegmentationService extends PubSubService {
|
||||
return;
|
||||
}
|
||||
|
||||
const segmentationState = cstSegmentation.state.getSegmentation(
|
||||
segmentationId
|
||||
);
|
||||
const segmentationState = cstSegmentation.state.getSegmentation(segmentationId);
|
||||
|
||||
if (!segmentationState) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
activeSegmentIndex,
|
||||
cachedStats,
|
||||
segmentsLocked,
|
||||
label,
|
||||
type,
|
||||
} = segmentationState;
|
||||
const { activeSegmentIndex, cachedStats, segmentsLocked, label, type } = segmentationState;
|
||||
|
||||
if (![LABELMAP, CONTOUR].includes(type)) {
|
||||
throw new Error(
|
||||
@@ -2018,10 +1824,7 @@ class SegmentationService extends PubSubService {
|
||||
try {
|
||||
this.addOrUpdateSegmentation(segmentationSchema);
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
`Failed to add/update segmentation ${segmentationId}`,
|
||||
error
|
||||
);
|
||||
console.warn(`Failed to add/update segmentation ${segmentationId}`, error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2037,9 +1840,7 @@ class SegmentationService extends PubSubService {
|
||||
);
|
||||
|
||||
if (!segmentationRepresentation) {
|
||||
throw new Error(
|
||||
'Must add representation to toolgroup before setting segments'
|
||||
);
|
||||
throw new Error('Must add representation to toolgroup before setting segments');
|
||||
}
|
||||
|
||||
const { segmentationRepresentationUID } = segmentationRepresentation;
|
||||
@@ -2057,14 +1858,11 @@ class SegmentationService extends PubSubService {
|
||||
return;
|
||||
}
|
||||
|
||||
const toolGroupIds = segmentationState.getToolGroupIdsWithSegmentation(
|
||||
segmentationId
|
||||
);
|
||||
const toolGroupIds = segmentationState.getToolGroupIdsWithSegmentation(segmentationId);
|
||||
|
||||
toolGroupIds.forEach(toolGroupId => {
|
||||
const segmentationRepresentations = segmentationState.getSegmentationRepresentations(
|
||||
toolGroupId
|
||||
);
|
||||
const segmentationRepresentations =
|
||||
segmentationState.getSegmentationRepresentations(toolGroupId);
|
||||
|
||||
const UIDsToRemove = [];
|
||||
segmentationRepresentations.forEach(representation => {
|
||||
@@ -2089,17 +1887,12 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
}
|
||||
|
||||
private _updateCornerstoneSegmentations({
|
||||
segmentationId,
|
||||
notYetUpdatedAtSource,
|
||||
}) {
|
||||
private _updateCornerstoneSegmentations({ segmentationId, notYetUpdatedAtSource }) {
|
||||
if (notYetUpdatedAtSource === false) {
|
||||
return;
|
||||
}
|
||||
const segmentationState = cstSegmentation.state;
|
||||
const sourceSegmentation = segmentationState.getSegmentation(
|
||||
segmentationId
|
||||
);
|
||||
const sourceSegmentation = segmentationState.getSegmentation(segmentationId);
|
||||
const segmentation = this.segmentations[segmentationId];
|
||||
const { label, cachedStats } = segmentation;
|
||||
|
||||
@@ -2115,14 +1908,11 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
private _updateCornerstoneSegmentationVisibility = segmentationId => {
|
||||
const segmentationState = cstSegmentation.state;
|
||||
const toolGroupIds = segmentationState.getToolGroupIdsWithSegmentation(
|
||||
segmentationId
|
||||
);
|
||||
const toolGroupIds = segmentationState.getToolGroupIdsWithSegmentation(segmentationId);
|
||||
|
||||
toolGroupIds.forEach(toolGroupId => {
|
||||
const segmentationRepresentations = cstSegmentation.state.getSegmentationRepresentations(
|
||||
toolGroupId
|
||||
);
|
||||
const segmentationRepresentations =
|
||||
cstSegmentation.state.getSegmentationRepresentations(toolGroupId);
|
||||
|
||||
if (segmentationRepresentations.length === 0) {
|
||||
return;
|
||||
@@ -2146,10 +1936,7 @@ class SegmentationService extends PubSubService {
|
||||
);
|
||||
|
||||
// update segments visibility
|
||||
const { segmentation } = this._getSegmentationInfo(
|
||||
segmentationId,
|
||||
toolGroupId
|
||||
);
|
||||
const { segmentation } = this._getSegmentationInfo(segmentationId, toolGroupId);
|
||||
|
||||
const segments = segmentation.segments.filter(Boolean);
|
||||
|
||||
@@ -2161,9 +1948,7 @@ class SegmentationService extends PubSubService {
|
||||
|
||||
private _getToolGroupIdsWithSegmentation(segmentationId: string) {
|
||||
const segmentationState = cstSegmentation.state;
|
||||
const toolGroupIds = segmentationState.getToolGroupIdsWithSegmentation(
|
||||
segmentationId
|
||||
);
|
||||
const toolGroupIds = segmentationState.getToolGroupIdsWithSegmentation(segmentationId);
|
||||
|
||||
return toolGroupIds;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import {
|
||||
synchronizers,
|
||||
SynchronizerManager,
|
||||
Synchronizer,
|
||||
} from '@cornerstonejs/tools';
|
||||
import { synchronizers, SynchronizerManager, Synchronizer } from '@cornerstonejs/tools';
|
||||
|
||||
import { pubSubServiceInterface, Types, ServicesManager } from '@ohif/core';
|
||||
|
||||
@@ -14,10 +10,7 @@ const EVENTS = {
|
||||
* @params options - are an optional set of options associated with the first
|
||||
* sync group declared.
|
||||
*/
|
||||
export type SyncCreator = (
|
||||
id: string,
|
||||
options?: Record<string, unknown>
|
||||
) => Synchronizer;
|
||||
export type SyncCreator = (id: string, options?: Record<string, unknown>) => Synchronizer;
|
||||
|
||||
export type SyncGroup = {
|
||||
type: string;
|
||||
@@ -40,9 +33,7 @@ export default class SyncGroupService {
|
||||
static REGISTRATION = {
|
||||
name: 'syncGroupService',
|
||||
altName: 'SyncGroupService',
|
||||
create: ({
|
||||
servicesManager,
|
||||
}: Types.Extensions.ExtensionParams): SyncGroupService => {
|
||||
create: ({ servicesManager }: Types.Extensions.ExtensionParams): SyncGroupService => {
|
||||
return new SyncGroupService(servicesManager);
|
||||
},
|
||||
};
|
||||
@@ -65,11 +56,7 @@ export default class SyncGroupService {
|
||||
Object.assign(this, pubSubServiceInterface);
|
||||
}
|
||||
|
||||
private _createSynchronizer(
|
||||
type: string,
|
||||
id: string,
|
||||
options
|
||||
): Synchronizer | undefined {
|
||||
private _createSynchronizer(type: string, id: string, options): Synchronizer | undefined {
|
||||
const syncCreator = this.synchronizerCreators[type.toLowerCase()];
|
||||
if (syncCreator) {
|
||||
return syncCreator(id, options);
|
||||
@@ -109,19 +96,11 @@ export default class SyncGroupService {
|
||||
return;
|
||||
}
|
||||
|
||||
const syncGroupsArray = Array.isArray(syncGroups)
|
||||
? syncGroups
|
||||
: [syncGroups];
|
||||
const syncGroupsArray = Array.isArray(syncGroups) ? syncGroups : [syncGroups];
|
||||
|
||||
syncGroupsArray.forEach(syncGroup => {
|
||||
const syncGroupObj = asSyncGroup(syncGroup);
|
||||
const {
|
||||
type,
|
||||
target = true,
|
||||
source = true,
|
||||
options = {},
|
||||
id = type,
|
||||
} = syncGroupObj;
|
||||
const { type, target = true, source = true, options = {}, id = type } = syncGroupObj;
|
||||
|
||||
const synchronizer = this._getOrCreateSynchronizer(type, id, options);
|
||||
synchronizer.setOptions(viewportId, options);
|
||||
|
||||
@@ -24,9 +24,7 @@ export default class ToolGroupService {
|
||||
public static REGISTRATION = {
|
||||
name: 'toolGroupService',
|
||||
altName: 'ToolGroupService',
|
||||
create: ({
|
||||
servicesManager,
|
||||
}: OhifTypes.Extensions.ExtensionParams): ToolGroupService => {
|
||||
create: ({ servicesManager }: OhifTypes.Extensions.ExtensionParams): ToolGroupService => {
|
||||
return new ToolGroupService(servicesManager);
|
||||
},
|
||||
};
|
||||
@@ -40,10 +38,7 @@ export default class ToolGroupService {
|
||||
EVENTS: { [key: string]: string };
|
||||
|
||||
constructor(serviceManager) {
|
||||
const {
|
||||
cornerstoneViewportService,
|
||||
viewportGridService,
|
||||
} = serviceManager.services;
|
||||
const { cornerstoneViewportService, viewportGridService } = serviceManager.services;
|
||||
this.cornerstoneViewportService = cornerstoneViewportService;
|
||||
this.viewportGridService = viewportGridService;
|
||||
this.listeners = {};
|
||||
@@ -66,19 +61,14 @@ export default class ToolGroupService {
|
||||
|
||||
if (!toolGroupIdToUse) {
|
||||
// Use the active viewport's tool group if no tool group id is provided
|
||||
const enabledElement = getActiveViewportEnabledElement(
|
||||
this.viewportGridService
|
||||
);
|
||||
const enabledElement = getActiveViewportEnabledElement(this.viewportGridService);
|
||||
|
||||
if (!enabledElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { renderingEngineId, viewportId } = enabledElement;
|
||||
const toolGroup = ToolGroupManager.getToolGroupForViewport(
|
||||
viewportId,
|
||||
renderingEngineId
|
||||
);
|
||||
const toolGroup = ToolGroupManager.getToolGroupForViewport(viewportId, renderingEngineId);
|
||||
|
||||
if (!toolGroup) {
|
||||
console.warn(
|
||||
@@ -103,10 +93,7 @@ export default class ToolGroupService {
|
||||
|
||||
public getToolGroupForViewport(viewportId: string): Types.IToolGroup | void {
|
||||
const renderingEngine = this.cornerstoneViewportService.getRenderingEngine();
|
||||
return ToolGroupManager.getToolGroupForViewport(
|
||||
viewportId,
|
||||
renderingEngine.id
|
||||
);
|
||||
return ToolGroupManager.getToolGroupForViewport(viewportId, renderingEngine.id);
|
||||
}
|
||||
|
||||
public getActiveToolForViewport(viewportId: string): string {
|
||||
@@ -133,10 +120,7 @@ export default class ToolGroupService {
|
||||
renderingEngineId: string,
|
||||
deleteToolGroupIfEmpty?: boolean
|
||||
): void {
|
||||
const toolGroup = ToolGroupManager.getToolGroupForViewport(
|
||||
viewportId,
|
||||
renderingEngineId
|
||||
);
|
||||
const toolGroup = ToolGroupManager.getToolGroupForViewport(viewportId, renderingEngineId);
|
||||
|
||||
if (!toolGroup) {
|
||||
return;
|
||||
@@ -193,11 +177,7 @@ export default class ToolGroupService {
|
||||
return toolGroup;
|
||||
}
|
||||
|
||||
public addToolsToToolGroup(
|
||||
toolGroupId: string,
|
||||
tools: Array<Tool>,
|
||||
configs: any = {}
|
||||
): void {
|
||||
public addToolsToToolGroup(toolGroupId: string, tools: Array<Tool>, configs: any = {}): void {
|
||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId);
|
||||
// this.changeConfigurationIfNecessary(toolGroup, volumeId);
|
||||
this._addTools(toolGroup, tools, configs);
|
||||
|
||||
+31
-110
@@ -12,10 +12,7 @@ import {
|
||||
Enums as csEnums,
|
||||
} from '@cornerstonejs/core';
|
||||
|
||||
import {
|
||||
utilities as csToolsUtils,
|
||||
Enums as csToolsEnums,
|
||||
} from '@cornerstonejs/tools';
|
||||
import { utilities as csToolsUtils, Enums as csToolsEnums } from '@cornerstonejs/tools';
|
||||
import { IViewportService } from './IViewportService';
|
||||
import { RENDERING_ENGINE_ID } from './constants';
|
||||
import ViewportInfo, {
|
||||
@@ -23,25 +20,20 @@ import ViewportInfo, {
|
||||
DisplaySetOptions,
|
||||
PublicViewportOptions,
|
||||
} from './Viewport';
|
||||
import {
|
||||
StackViewportData,
|
||||
VolumeViewportData,
|
||||
} from '../../types/CornerstoneCacheService';
|
||||
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
|
||||
import { Presentation, Presentations } from '../../types/Presentation';
|
||||
|
||||
import JumpPresets from '../../utils/JumpPresets';
|
||||
|
||||
const EVENTS = {
|
||||
VIEWPORT_DATA_CHANGED:
|
||||
'event::cornerstoneViewportService:viewportDataChanged',
|
||||
VIEWPORT_DATA_CHANGED: 'event::cornerstoneViewportService:viewportDataChanged',
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles cornerstone viewport logic including enabling, disabling, and
|
||||
* updating the viewport.
|
||||
*/
|
||||
class CornerstoneViewportService extends PubSubService
|
||||
implements IViewportService {
|
||||
class CornerstoneViewportService extends PubSubService implements IViewportService {
|
||||
static REGISTRATION = {
|
||||
name: 'cornerstoneViewportService',
|
||||
altName: 'CornerstoneViewportService',
|
||||
@@ -182,8 +174,7 @@ class CornerstoneViewportService extends PubSubService
|
||||
const camera = csViewport.getCamera();
|
||||
return {
|
||||
presentationIds,
|
||||
viewportType:
|
||||
!viewportType || viewportType === 'stack' ? 'stack' : 'volume',
|
||||
viewportType: !viewportType || viewportType === 'stack' ? 'stack' : 'volume',
|
||||
properties,
|
||||
initialImageIndex,
|
||||
camera,
|
||||
@@ -202,10 +193,7 @@ class CornerstoneViewportService extends PubSubService
|
||||
if (!presentation || !presentation.presentationIds) {
|
||||
return;
|
||||
}
|
||||
const {
|
||||
lutPresentationStore,
|
||||
positionPresentationStore,
|
||||
} = stateSyncService.getState();
|
||||
const { lutPresentationStore, positionPresentationStore } = stateSyncService.getState();
|
||||
const { presentationIds } = presentation;
|
||||
const { lutPresentationId, positionPresentationId } = presentationIds || {};
|
||||
const storeState = {};
|
||||
@@ -258,12 +246,8 @@ class CornerstoneViewportService extends PubSubService
|
||||
|
||||
// override the viewportOptions and displaySetOptions with the public ones
|
||||
// since those are the newly set ones, we set them here so that it handles defaults
|
||||
const displaySetOptions = viewportInfo.setPublicDisplaySetOptions(
|
||||
publicDisplaySetOptions
|
||||
);
|
||||
const viewportOptions = viewportInfo.setPublicViewportOptions(
|
||||
publicViewportOptions
|
||||
);
|
||||
const displaySetOptions = viewportInfo.setPublicDisplaySetOptions(publicDisplaySetOptions);
|
||||
const viewportOptions = viewportInfo.setPublicViewportOptions(publicViewportOptions);
|
||||
|
||||
const element = viewportInfo.getElement();
|
||||
const type = viewportInfo.getViewportType();
|
||||
@@ -317,11 +301,7 @@ class CornerstoneViewportService extends PubSubService
|
||||
): Types.IStackViewport | Types.IVolumeViewport | null {
|
||||
const viewportInfo = this.getViewportInfo(viewportId);
|
||||
|
||||
if (
|
||||
!viewportInfo ||
|
||||
!this.renderingEngine ||
|
||||
this.renderingEngine.hasBeenDestroyed
|
||||
) {
|
||||
if (!viewportInfo || !this.renderingEngine || this.renderingEngine.hasBeenDestroyed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -342,24 +322,15 @@ class CornerstoneViewportService extends PubSubService
|
||||
): void {
|
||||
const displaySetOptions = viewportInfo.getDisplaySetOptions();
|
||||
|
||||
const {
|
||||
imageIds,
|
||||
initialImageIndex,
|
||||
displaySetInstanceUID,
|
||||
} = viewportData.data;
|
||||
const { imageIds, initialImageIndex, displaySetInstanceUID } = viewportData.data;
|
||||
|
||||
this.viewportsDisplaySets.set(viewport.id, [displaySetInstanceUID]);
|
||||
|
||||
let initialImageIndexToUse =
|
||||
presentations?.positionPresentation?.initialImageIndex ??
|
||||
initialImageIndex;
|
||||
presentations?.positionPresentation?.initialImageIndex ?? initialImageIndex;
|
||||
|
||||
if (
|
||||
initialImageIndexToUse === undefined ||
|
||||
initialImageIndexToUse === null
|
||||
) {
|
||||
initialImageIndexToUse =
|
||||
this._getInitialImageIndexForViewport(viewportInfo, imageIds) || 0;
|
||||
if (initialImageIndexToUse === undefined || initialImageIndexToUse === null) {
|
||||
initialImageIndexToUse = this._getInitialImageIndexForViewport(viewportInfo, imageIds) || 0;
|
||||
}
|
||||
|
||||
const properties = { ...presentations.lutPresentation?.properties };
|
||||
@@ -404,12 +375,8 @@ class CornerstoneViewportService extends PubSubService
|
||||
if (viewportType === csEnums.ViewportType.STACK) {
|
||||
numberOfSlices = imageIds.length;
|
||||
} else if (viewportType === csEnums.ViewportType.ORTHOGRAPHIC) {
|
||||
const viewport = this.getCornerstoneViewport(
|
||||
viewportInfo.getViewportId()
|
||||
);
|
||||
const imageSliceData = csUtils.getImageSliceDataForVolumeViewport(
|
||||
viewport
|
||||
);
|
||||
const viewport = this.getCornerstoneViewport(viewportInfo.getViewportId());
|
||||
const imageSliceData = csUtils.getImageSliceDataForVolumeViewport(viewport);
|
||||
|
||||
if (!imageSliceData) {
|
||||
return;
|
||||
@@ -423,11 +390,7 @@ class CornerstoneViewportService extends PubSubService
|
||||
return this._getInitialImageIndex(numberOfSlices, index, preset);
|
||||
}
|
||||
|
||||
_getInitialImageIndex(
|
||||
numberOfSlices: number,
|
||||
imageIndex?: number,
|
||||
preset?: JumpPresets
|
||||
): number {
|
||||
_getInitialImageIndex(numberOfSlices: number, imageIndex?: number, preset?: JumpPresets): number {
|
||||
const lastSliceIndex = numberOfSlices - 1;
|
||||
|
||||
if (imageIndex !== undefined) {
|
||||
@@ -449,9 +412,7 @@ class CornerstoneViewportService extends PubSubService
|
||||
// it will jump to a different slice than the middle one which
|
||||
// was the initial slice, and we have some tools such as Crosshairs
|
||||
// which rely on a relative camera modifications and those will break.
|
||||
return lastSliceIndex % 2 === 0
|
||||
? lastSliceIndex / 2
|
||||
: (lastSliceIndex + 1) / 2;
|
||||
return lastSliceIndex % 2 === 0 ? lastSliceIndex / 2 : (lastSliceIndex + 1) / 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -521,22 +482,11 @@ class CornerstoneViewportService extends PubSubService
|
||||
});
|
||||
|
||||
// This returns the async continuation only
|
||||
return this.setVolumesForViewport(
|
||||
viewport,
|
||||
volumeInputArray,
|
||||
presentations
|
||||
);
|
||||
return this.setVolumesForViewport(viewport, volumeInputArray, presentations);
|
||||
}
|
||||
|
||||
public async setVolumesForViewport(
|
||||
viewport,
|
||||
volumeInputArray,
|
||||
presentations
|
||||
) {
|
||||
const {
|
||||
displaySetService,
|
||||
toolGroupService,
|
||||
} = this.servicesManager.services;
|
||||
public async setVolumesForViewport(viewport, volumeInputArray, presentations) {
|
||||
const { displaySetService, toolGroupService } = this.servicesManager.services;
|
||||
|
||||
const viewportInfo = this.getViewportInfo(viewport.id);
|
||||
const displaySetOptions = viewportInfo.getDisplaySetOptions();
|
||||
@@ -594,10 +544,7 @@ class CornerstoneViewportService extends PubSubService
|
||||
// associated with the primary displaySet
|
||||
|
||||
// get segmentations only returns the hydrated segmentations
|
||||
this._addSegmentationRepresentationToToolGroupIfNecessary(
|
||||
displaySetInstanceUIDs,
|
||||
viewport
|
||||
);
|
||||
this._addSegmentationRepresentationToToolGroupIfNecessary(displaySetInstanceUIDs, viewport);
|
||||
}
|
||||
|
||||
const toolGroup = toolGroupService.getToolGroupForViewport(viewport.id);
|
||||
@@ -618,10 +565,7 @@ class CornerstoneViewportService extends PubSubService
|
||||
displaySetInstanceUIDs: string[],
|
||||
viewport: any
|
||||
) {
|
||||
const {
|
||||
segmentationService,
|
||||
toolGroupService,
|
||||
} = this.servicesManager.services;
|
||||
const { segmentationService, toolGroupService } = this.servicesManager.services;
|
||||
|
||||
const toolGroup = toolGroupService.getToolGroupForViewport(viewport.id);
|
||||
|
||||
@@ -630,9 +574,7 @@ class CornerstoneViewportService extends PubSubService
|
||||
|
||||
for (const segmentation of segmentations) {
|
||||
const toolGroupSegmentationRepresentations =
|
||||
segmentationService.getSegmentationRepresentationsForToolGroup(
|
||||
toolGroup.id
|
||||
) || [];
|
||||
segmentationService.getSegmentationRepresentationsForToolGroup(toolGroup.id) || [];
|
||||
|
||||
// if there is already a segmentation representation for this segmentation
|
||||
// for this toolGroup, don't bother at all
|
||||
@@ -647,16 +589,12 @@ class CornerstoneViewportService extends PubSubService
|
||||
// otherwise, check if the hydrated segmentations are in the same FOR
|
||||
// as the primary displaySet, if so add the representation (since it was not there)
|
||||
const { id: segDisplaySetInstanceUID, type } = segmentation;
|
||||
const segFrameOfReferenceUID = this._getFrameOfReferenceUID(
|
||||
segDisplaySetInstanceUID
|
||||
);
|
||||
const segFrameOfReferenceUID = this._getFrameOfReferenceUID(segDisplaySetInstanceUID);
|
||||
|
||||
let shouldDisplaySeg = false;
|
||||
|
||||
for (const displaySetInstanceUID of displaySetInstanceUIDs) {
|
||||
const primaryFrameOfReferenceUID = this._getFrameOfReferenceUID(
|
||||
displaySetInstanceUID
|
||||
);
|
||||
const primaryFrameOfReferenceUID = this._getFrameOfReferenceUID(displaySetInstanceUID);
|
||||
|
||||
if (segFrameOfReferenceUID === primaryFrameOfReferenceUID) {
|
||||
shouldDisplaySeg = true;
|
||||
@@ -677,14 +615,8 @@ class CornerstoneViewportService extends PubSubService
|
||||
}
|
||||
}
|
||||
|
||||
private addOverlayRepresentationForDisplaySet(
|
||||
displaySet: any,
|
||||
viewport: any
|
||||
) {
|
||||
const {
|
||||
segmentationService,
|
||||
toolGroupService,
|
||||
} = this.servicesManager.services;
|
||||
private addOverlayRepresentationForDisplaySet(displaySet: any, viewport: any) {
|
||||
const { segmentationService, toolGroupService } = this.servicesManager.services;
|
||||
|
||||
const { referencedVolumeId } = displaySet;
|
||||
const segmentationId = displaySet.displaySetInstanceUID;
|
||||
@@ -711,10 +643,7 @@ class CornerstoneViewportService extends PubSubService
|
||||
const viewport = this.getCornerstoneViewport(viewportId);
|
||||
const viewportCamera = viewport.getCamera();
|
||||
|
||||
if (
|
||||
viewport instanceof VolumeViewport ||
|
||||
viewport instanceof VolumeViewport3D
|
||||
) {
|
||||
if (viewport instanceof VolumeViewport || viewport instanceof VolumeViewport3D) {
|
||||
this._setVolumeViewport(viewport, viewportData, viewportInfo).then(() => {
|
||||
if (keepCamera) {
|
||||
viewport.setCamera(viewportCamera);
|
||||
@@ -744,10 +673,7 @@ class CornerstoneViewportService extends PubSubService
|
||||
viewportInfo,
|
||||
presentations
|
||||
);
|
||||
} else if (
|
||||
viewport instanceof VolumeViewport ||
|
||||
viewport instanceof VolumeViewport3D
|
||||
) {
|
||||
} else if (viewport instanceof VolumeViewport || viewport instanceof VolumeViewport3D) {
|
||||
this._setVolumeViewport(
|
||||
viewport,
|
||||
viewportData as VolumeViewportData,
|
||||
@@ -770,10 +696,7 @@ class CornerstoneViewportService extends PubSubService
|
||||
|
||||
_getSlabThickness(displaySetOptions, volumeId) {
|
||||
const { blendMode } = displaySetOptions;
|
||||
if (
|
||||
blendMode === undefined ||
|
||||
displaySetOptions.slabThickness === undefined
|
||||
) {
|
||||
if (blendMode === undefined || displaySetOptions.slabThickness === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -799,9 +722,7 @@ class CornerstoneViewportService extends PubSubService
|
||||
|
||||
_getFrameOfReferenceUID(displaySetInstanceUID) {
|
||||
const { displaySetService } = this.servicesManager.services;
|
||||
const displaySet = displaySetService.getDisplaySetByUID(
|
||||
displaySetInstanceUID
|
||||
);
|
||||
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||
|
||||
if (!displaySet) {
|
||||
return;
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import { Types } from '@cornerstonejs/core';
|
||||
import { StackData, VolumeData } from '../../types/CornerstoneCacheService';
|
||||
import {
|
||||
DisplaySetOptions,
|
||||
PublicViewportOptions,
|
||||
ViewportOptions,
|
||||
} from './Viewport';
|
||||
import { DisplaySetOptions, PublicViewportOptions, ViewportOptions } from './Viewport';
|
||||
|
||||
/**
|
||||
* Handles cornerstone viewport logic including enabling, disabling, and
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { Types, Enums } from '@cornerstonejs/core';
|
||||
import { Types as UITypes } from '@ohif/ui';
|
||||
import {
|
||||
StackViewportData,
|
||||
VolumeViewportData,
|
||||
} from '../../types/CornerstoneCacheService';
|
||||
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
|
||||
import getCornerstoneBlendMode from '../../utils/getCornerstoneBlendMode';
|
||||
import getCornerstoneOrientation from '../../utils/getCornerstoneOrientation';
|
||||
import getCornerstoneViewportType from '../../utils/getCornerstoneViewportType';
|
||||
@@ -90,11 +87,7 @@ const DEFAULT_TOOLGROUP_ID = 'default';
|
||||
|
||||
// Return true if the data contains the given display set UID OR the imageId
|
||||
// if it is a composite object.
|
||||
const dataContains = (
|
||||
data,
|
||||
displaySetUID: string,
|
||||
imageId?: string
|
||||
): boolean => {
|
||||
const dataContains = (data, displaySetUID: string, imageId?: string): boolean => {
|
||||
if (data.displaySetInstanceUID === displaySetUID) {
|
||||
return true;
|
||||
}
|
||||
@@ -128,9 +121,7 @@ class ViewportInfo {
|
||||
}
|
||||
|
||||
if (this.viewportData.data.length) {
|
||||
return !!this.viewportData.data.find(data =>
|
||||
dataContains(data, displaySetUID, imageId)
|
||||
);
|
||||
return !!this.viewportData.data.find(data => dataContains(data, displaySetUID, imageId));
|
||||
}
|
||||
return dataContains(this.viewportData.data, displaySetUID, imageId);
|
||||
}
|
||||
@@ -158,9 +149,7 @@ class ViewportInfo {
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
public setViewportData(
|
||||
viewportData: StackViewportData | VolumeViewportData
|
||||
): void {
|
||||
public setViewportData(viewportData: StackViewportData | VolumeViewportData): void {
|
||||
this.viewportData = viewportData;
|
||||
}
|
||||
|
||||
@@ -168,7 +157,6 @@ class ViewportInfo {
|
||||
return this.viewportData;
|
||||
}
|
||||
|
||||
|
||||
public getElement(): HTMLDivElement {
|
||||
return this.element;
|
||||
}
|
||||
@@ -181,13 +169,11 @@ class ViewportInfo {
|
||||
publicDisplaySetOptions: PublicDisplaySetOptions[] | DisplaySetSelector[]
|
||||
): Array<DisplaySetOptions> {
|
||||
// map the displaySetOptions and check if they are undefined then set them to default values
|
||||
const displaySetOptions = this.mapDisplaySetOptions(
|
||||
publicDisplaySetOptions
|
||||
);
|
||||
const displaySetOptions = this.mapDisplaySetOptions(publicDisplaySetOptions);
|
||||
|
||||
this.setDisplaySetOptions(displaySetOptions);
|
||||
|
||||
return this.displaySetOptions
|
||||
return this.displaySetOptions;
|
||||
}
|
||||
|
||||
public hasDisplaySet(displaySetInstanceUID: string): boolean {
|
||||
@@ -196,8 +182,9 @@ class ViewportInfo {
|
||||
// via cornerstoneViewportService
|
||||
let viewportData = this.getViewportData();
|
||||
|
||||
if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC ||
|
||||
viewportData.viewportType === Enums.ViewportType.VOLUME_3D
|
||||
if (
|
||||
viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC ||
|
||||
viewportData.viewportType === Enums.ViewportType.VOLUME_3D
|
||||
) {
|
||||
viewportData = viewportData as VolumeViewportData;
|
||||
return viewportData.data.some(
|
||||
@@ -209,22 +196,15 @@ class ViewportInfo {
|
||||
return viewportData.data.displaySetInstanceUID === displaySetInstanceUID;
|
||||
}
|
||||
|
||||
public setPublicViewportOptions(
|
||||
viewportOptionsEntry: PublicViewportOptions
|
||||
): ViewportOptions {
|
||||
public setPublicViewportOptions(viewportOptionsEntry: PublicViewportOptions): ViewportOptions {
|
||||
let viewportType = viewportOptionsEntry.viewportType;
|
||||
const {
|
||||
toolGroupId = DEFAULT_TOOLGROUP_ID,
|
||||
presentationIds,
|
||||
} = viewportOptionsEntry;
|
||||
const { toolGroupId = DEFAULT_TOOLGROUP_ID, presentationIds } = viewportOptionsEntry;
|
||||
let orientation;
|
||||
|
||||
if (!viewportType) {
|
||||
viewportType = getCornerstoneViewportType(STACK);
|
||||
} else {
|
||||
viewportType = getCornerstoneViewportType(
|
||||
viewportOptionsEntry.viewportType
|
||||
);
|
||||
viewportType = getCornerstoneViewportType(viewportOptionsEntry.viewportType);
|
||||
}
|
||||
|
||||
// map SAGITTAL, AXIAL, CORONAL orientation to be used by cornerstone
|
||||
@@ -256,9 +236,7 @@ class ViewportInfo {
|
||||
return this.viewportOptions;
|
||||
}
|
||||
|
||||
public setDisplaySetOptions(
|
||||
displaySetOptions: Array<DisplaySetOptions>
|
||||
): void {
|
||||
public setDisplaySetOptions(displaySetOptions: Array<DisplaySetOptions>): void {
|
||||
this.displaySetOptions = displaySetOptions;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,11 +9,7 @@ const state = {
|
||||
* @param {HTMLElement} dom Active viewport element.
|
||||
* @return void
|
||||
*/
|
||||
const setEnabledElement = (
|
||||
viewportId: string,
|
||||
element: HTMLElement,
|
||||
context?: string
|
||||
): void => {
|
||||
const setEnabledElement = (viewportId: string, element: HTMLElement, context?: string): void => {
|
||||
const targetContext = context || state.DEFAULT_CONTEXT;
|
||||
|
||||
state.enabledElements[viewportId] = {
|
||||
|
||||
@@ -25,8 +25,7 @@ class CalibrationLineTool extends LengthTool {
|
||||
this._renderingViewport.worldToCanvas(p)
|
||||
);
|
||||
// for display, round to 2 decimal points
|
||||
const lengthPx =
|
||||
Math.round(calculateLength2(canvasPoint1, canvasPoint2) * 100) / 100;
|
||||
const lengthPx = Math.round(calculateLength2(canvasPoint1, canvasPoint2) * 100) / 100;
|
||||
|
||||
const textLines = [`${lengthPx}px`];
|
||||
|
||||
@@ -64,17 +63,11 @@ export function onCompletedCalibrationLine(servicesManager, csToolsEvent) {
|
||||
|
||||
const length =
|
||||
Math.round(
|
||||
calculateLength3(
|
||||
annotationData.handles.points[0],
|
||||
annotationData.handles.points[1]
|
||||
) * 100
|
||||
calculateLength3(annotationData.handles.points[0], annotationData.handles.points[1]) * 100
|
||||
) / 100;
|
||||
|
||||
// calculate the currently applied pixel spacing on the viewport
|
||||
const calibratedPixelSpacing = metaData.get(
|
||||
'calibratedPixelSpacing',
|
||||
imageId
|
||||
);
|
||||
const calibratedPixelSpacing = metaData.get('calibratedPixelSpacing', imageId);
|
||||
const imagePlaneModule = metaData.get('imagePlaneModule', imageId);
|
||||
const currentRowPixelSpacing =
|
||||
calibratedPixelSpacing?.[0] || imagePlaneModule?.rowPixelSpacing || 1;
|
||||
@@ -87,12 +80,7 @@ export function onCompletedCalibrationLine(servicesManager, csToolsEvent) {
|
||||
const colSpacing = spacingScale * currentColumnPixelSpacing;
|
||||
|
||||
// trigger resize of the viewport to adjust the world/pixel mapping
|
||||
calibrateImageSpacing(
|
||||
imageId,
|
||||
viewport.getRenderingEngine(),
|
||||
rowSpacing,
|
||||
colSpacing
|
||||
);
|
||||
calibrateImageSpacing(imageId, viewport.getRenderingEngine(), rowSpacing, colSpacing);
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import * as CornerstoneCacheService from './CornerstoneCacheService'
|
||||
import * as CornerstoneCacheService from './CornerstoneCacheService';
|
||||
import CornerstoneServices from './CornerstoneServices';
|
||||
|
||||
export type {
|
||||
CornerstoneCacheService,
|
||||
CornerstoneServices,
|
||||
}
|
||||
export type { CornerstoneCacheService, CornerstoneServices };
|
||||
@@ -27,31 +27,22 @@ const CornerstoneViewportDownloadForm = ({
|
||||
const activeViewportElement = enabledElement?.element;
|
||||
const activeViewportEnabledElement = getEnabledElement(activeViewportElement);
|
||||
|
||||
const {
|
||||
viewportId: activeViewportId,
|
||||
renderingEngineId,
|
||||
} = activeViewportEnabledElement;
|
||||
const { viewportId: activeViewportId, renderingEngineId } = activeViewportEnabledElement;
|
||||
|
||||
const toolGroup = ToolGroupManager.getToolGroupForViewport(
|
||||
activeViewportId,
|
||||
renderingEngineId
|
||||
);
|
||||
const toolGroup = ToolGroupManager.getToolGroupForViewport(activeViewportId, renderingEngineId);
|
||||
|
||||
const toolModeAndBindings = Object.keys(toolGroup.toolOptions).reduce(
|
||||
(acc, toolName) => {
|
||||
const tool = toolGroup.toolOptions[toolName];
|
||||
const { mode, bindings } = tool;
|
||||
const toolModeAndBindings = Object.keys(toolGroup.toolOptions).reduce((acc, toolName) => {
|
||||
const tool = toolGroup.toolOptions[toolName];
|
||||
const { mode, bindings } = tool;
|
||||
|
||||
return {
|
||||
...acc,
|
||||
[toolName]: {
|
||||
mode,
|
||||
bindings,
|
||||
},
|
||||
};
|
||||
},
|
||||
{}
|
||||
);
|
||||
return {
|
||||
...acc,
|
||||
[toolName]: {
|
||||
mode,
|
||||
bindings,
|
||||
},
|
||||
};
|
||||
}, {});
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
@@ -64,9 +55,7 @@ const CornerstoneViewportDownloadForm = ({
|
||||
|
||||
const enableViewport = viewportElement => {
|
||||
if (viewportElement) {
|
||||
const { renderingEngine, viewport } = getEnabledElement(
|
||||
activeViewportElement
|
||||
);
|
||||
const { renderingEngine, viewport } = getEnabledElement(activeViewportElement);
|
||||
|
||||
const viewportInput = {
|
||||
viewportId: VIEWPORT_ID,
|
||||
@@ -91,11 +80,7 @@ const CornerstoneViewportDownloadForm = ({
|
||||
}
|
||||
};
|
||||
|
||||
const updateViewportPreview = (
|
||||
downloadViewportElement,
|
||||
internalCanvas,
|
||||
fileType
|
||||
) =>
|
||||
const updateViewportPreview = (downloadViewportElement, internalCanvas, fileType) =>
|
||||
new Promise(resolve => {
|
||||
const enabledElement = getEnabledElement(downloadViewportElement);
|
||||
|
||||
@@ -133,10 +118,7 @@ const CornerstoneViewportDownloadForm = ({
|
||||
|
||||
resolve({ dataUrl, width: newWidth, height: newHeight });
|
||||
|
||||
downloadViewportElement.removeEventListener(
|
||||
Enums.Events.IMAGE_RENDERED,
|
||||
updateViewport
|
||||
);
|
||||
downloadViewportElement.removeEventListener(Enums.Events.IMAGE_RENDERED, updateViewport);
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -144,9 +126,7 @@ const CornerstoneViewportDownloadForm = ({
|
||||
const loadImage = (activeViewportElement, viewportElement, width, height) =>
|
||||
new Promise(resolve => {
|
||||
if (activeViewportElement && viewportElement) {
|
||||
const activeViewportEnabledElement = getEnabledElement(
|
||||
activeViewportElement
|
||||
);
|
||||
const activeViewportEnabledElement = getEnabledElement(activeViewportElement);
|
||||
|
||||
if (!activeViewportEnabledElement) {
|
||||
return;
|
||||
@@ -165,10 +145,7 @@ const CornerstoneViewportDownloadForm = ({
|
||||
downloadViewport.setProperties(properties);
|
||||
|
||||
const newWidth = Math.min(width || image.width, MAX_TEXTURE_SIZE);
|
||||
const newHeight = Math.min(
|
||||
height || image.height,
|
||||
MAX_TEXTURE_SIZE
|
||||
);
|
||||
const newHeight = Math.min(height || image.height, MAX_TEXTURE_SIZE);
|
||||
|
||||
resolve({ width: newWidth, height: newHeight });
|
||||
});
|
||||
@@ -190,31 +167,19 @@ const CornerstoneViewportDownloadForm = ({
|
||||
}
|
||||
});
|
||||
|
||||
const toggleAnnotations = (
|
||||
toggle,
|
||||
viewportElement,
|
||||
activeViewportElement
|
||||
) => {
|
||||
const activeViewportEnabledElement = getEnabledElement(
|
||||
activeViewportElement
|
||||
);
|
||||
const toggleAnnotations = (toggle, viewportElement, activeViewportElement) => {
|
||||
const activeViewportEnabledElement = getEnabledElement(activeViewportElement);
|
||||
|
||||
const downloadViewportElement = getEnabledElement(viewportElement);
|
||||
|
||||
const {
|
||||
viewportId: activeViewportId,
|
||||
renderingEngineId,
|
||||
} = activeViewportEnabledElement;
|
||||
const { viewportId: activeViewportId, renderingEngineId } = activeViewportEnabledElement;
|
||||
const { viewportId: downloadViewportId } = downloadViewportElement;
|
||||
|
||||
if (!activeViewportEnabledElement || !downloadViewportElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const toolGroup = ToolGroupManager.getToolGroupForViewport(
|
||||
activeViewportId,
|
||||
renderingEngineId
|
||||
);
|
||||
const toolGroup = ToolGroupManager.getToolGroupForViewport(activeViewportId, renderingEngineId);
|
||||
|
||||
// add the viewport to the toolGroup
|
||||
toolGroup.addViewport(downloadViewportId, renderingEngineId);
|
||||
|
||||
@@ -98,22 +98,13 @@ export default class DicomFileUploader extends PubSubService {
|
||||
});
|
||||
},
|
||||
timeout: () => {
|
||||
this._reject(
|
||||
reject,
|
||||
new UploadRejection(UploadStatus.Failed, 'The request timed out.')
|
||||
);
|
||||
this._reject(reject, new UploadRejection(UploadStatus.Failed, 'The request timed out.'));
|
||||
},
|
||||
abort: () => {
|
||||
this._reject(
|
||||
reject,
|
||||
new UploadRejection(UploadStatus.Cancelled, 'Cancelled')
|
||||
);
|
||||
this._reject(reject, new UploadRejection(UploadStatus.Cancelled, 'Cancelled'));
|
||||
},
|
||||
error: () => {
|
||||
this._reject(
|
||||
reject,
|
||||
new UploadRejection(UploadStatus.Failed, 'The request failed.')
|
||||
);
|
||||
this._reject(reject, new UploadRejection(UploadStatus.Failed, 'The request failed.'));
|
||||
},
|
||||
};
|
||||
|
||||
@@ -122,10 +113,7 @@ export default class DicomFileUploader extends PubSubService {
|
||||
.loadFileRequest(this._fileId)
|
||||
.then(dicomFile => {
|
||||
if (this._abortController.signal.aborted) {
|
||||
this._reject(
|
||||
reject,
|
||||
new UploadRejection(UploadStatus.Cancelled, 'Cancelled')
|
||||
);
|
||||
this._reject(reject, new UploadRejection(UploadStatus.Cancelled, 'Cancelled'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -133,10 +121,7 @@ export default class DicomFileUploader extends PubSubService {
|
||||
// The file is not DICOM
|
||||
this._reject(
|
||||
reject,
|
||||
new UploadRejection(
|
||||
UploadStatus.Failed,
|
||||
'Not a valid DICOM file.'
|
||||
)
|
||||
new UploadRejection(UploadStatus.Failed, 'Not a valid DICOM file.')
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -164,10 +149,7 @@ export default class DicomFileUploader extends PubSubService {
|
||||
}
|
||||
|
||||
private _isRejected(): boolean {
|
||||
return (
|
||||
this._status === UploadStatus.Failed ||
|
||||
this._status === UploadStatus.Cancelled
|
||||
);
|
||||
return this._status === UploadStatus.Failed || this._status === UploadStatus.Cancelled;
|
||||
}
|
||||
|
||||
private _reject(reject: (reason?: any) => void, reason: any) {
|
||||
|
||||
@@ -21,11 +21,7 @@ function callInputDialog(
|
||||
dialogConfig: any = {}
|
||||
) {
|
||||
const dialogId = 'dialog-enter-annotation';
|
||||
const label = data
|
||||
? isArrowAnnotateInputDialog
|
||||
? data.text
|
||||
: data.label
|
||||
: '';
|
||||
const label = data ? (isArrowAnnotateInputDialog ? data.text : data.label) : '';
|
||||
const {
|
||||
dialogTitle = 'Annotation',
|
||||
inputLabel = 'Enter your annotation',
|
||||
@@ -69,7 +65,7 @@ function callInputDialog(
|
||||
return (
|
||||
<Input
|
||||
autoFocus
|
||||
className="bg-black border-primary-main"
|
||||
className="border-primary-main bg-black"
|
||||
type="text"
|
||||
id="annotation"
|
||||
label={inputLabel}
|
||||
|
||||
@@ -8,9 +8,7 @@ const getImageId = imageObj => {
|
||||
return;
|
||||
}
|
||||
|
||||
return typeof imageObj.getImageId === 'function'
|
||||
? imageObj.getImageId()
|
||||
: imageObj.url;
|
||||
return typeof imageObj.getImageId === 'function' ? imageObj.getImageId() : imageObj.url;
|
||||
};
|
||||
|
||||
const findImageIdOnStudies = (studies, displaySetInstanceUID) => {
|
||||
@@ -163,9 +161,7 @@ class DicomLoaderService {
|
||||
getDicomDataMethod = fetchIt.bind(this, imageId);
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
`Unsupported image type: ${loaderType} for imageId: ${imageId}`
|
||||
);
|
||||
throw new Error(`Unsupported image type: ${loaderType} for imageId: ${imageId}`);
|
||||
}
|
||||
|
||||
return getDicomDataMethod();
|
||||
|
||||
@@ -3,9 +3,7 @@ import { IEnabledElement } from '@cornerstonejs/core/dist/esm/types';
|
||||
|
||||
import { getEnabledElement as OHIFgetEnabledElement } from '../state';
|
||||
|
||||
export default function getActiveViewportEnabledElement(
|
||||
viewportGridService
|
||||
): IEnabledElement {
|
||||
export default function getActiveViewportEnabledElement(viewportGridService): IEnabledElement {
|
||||
const { activeViewportId } = viewportGridService.getState();
|
||||
const { element } = OHIFgetEnabledElement(activeViewportId) || {};
|
||||
const enabledElement = getEnabledElement(element);
|
||||
|
||||
@@ -2,9 +2,7 @@ import { Enums } from '@cornerstonejs/core';
|
||||
|
||||
const MIP = 'mip';
|
||||
|
||||
export default function getCornerstoneBlendMode(
|
||||
blendMode: string
|
||||
): Enums.BlendModes {
|
||||
export default function getCornerstoneBlendMode(blendMode: string): Enums.BlendModes {
|
||||
if (!blendMode) {
|
||||
return Enums.BlendModes.COMPOSITE;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@ const AXIAL = 'axial';
|
||||
const SAGITTAL = 'sagittal';
|
||||
const CORONAL = 'coronal';
|
||||
|
||||
export default function getCornerstoneOrientation(
|
||||
orientation: string
|
||||
): Enums.OrientationAxis {
|
||||
export default function getCornerstoneOrientation(orientation: string): Enums.OrientationAxis {
|
||||
if (orientation) {
|
||||
switch (orientation.toLowerCase()) {
|
||||
case AXIAL:
|
||||
|
||||
@@ -5,9 +5,7 @@ const VOLUME = 'volume';
|
||||
const ORTHOGRAPHIC = 'orthographic';
|
||||
const VOLUME_3D = 'volume3d';
|
||||
|
||||
export default function getCornerstoneViewportType(
|
||||
viewportType: string
|
||||
): Enums.ViewportType {
|
||||
export default function getCornerstoneViewportType(viewportType: string): Enums.ViewportType {
|
||||
const lowerViewportType = viewportType.toLowerCase();
|
||||
if (lowerViewportType === STACK) {
|
||||
return Enums.ViewportType.STACK;
|
||||
@@ -21,7 +19,5 @@ export default function getCornerstoneViewportType(
|
||||
return Enums.ViewportType.VOLUME_3D;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Invalid viewport type: ${viewportType}. Valid types are: stack, volume`
|
||||
);
|
||||
throw new Error(`Invalid viewport type: ${viewportType}. Valid types are: stack, volume`);
|
||||
}
|
||||
@@ -19,11 +19,7 @@ export default function getNthFrames(imageIds) {
|
||||
const centerEnd = centerStart + 6;
|
||||
|
||||
for (let i = 0; i < imageIds.length; i++) {
|
||||
if (
|
||||
i < 2 ||
|
||||
i > imageIds.length - 4 ||
|
||||
(i > centerStart && i < centerEnd)
|
||||
) {
|
||||
if (i < 2 || i > imageIds.length - 4 || (i > centerStart && i < centerEnd)) {
|
||||
frames[0].push(imageIds[i]);
|
||||
} else if (i % 7 === 2) {
|
||||
frames[1].push(imageIds[i]);
|
||||
@@ -33,12 +29,6 @@ export default function getNthFrames(imageIds) {
|
||||
frames[(i % 2) + 3].push(imageIds[i]);
|
||||
}
|
||||
}
|
||||
const ret = [
|
||||
...frames[0],
|
||||
...frames[1],
|
||||
...frames[2],
|
||||
...frames[3],
|
||||
...frames[4],
|
||||
];
|
||||
const ret = [...frames[0], ...frames[1], ...frames[2], ...frames[3], ...frames[4]];
|
||||
return ret;
|
||||
}
|
||||
@@ -105,9 +105,7 @@ export default function interleaveCenterLoader({
|
||||
const { imageId } = request;
|
||||
|
||||
AllRequests.forEach(volumeRequests => {
|
||||
const volumeImageIdRequest = volumeRequests.find(
|
||||
req => req.imageId === imageId
|
||||
);
|
||||
const volumeImageIdRequest = volumeRequests.find(req => req.imageId === imageId);
|
||||
if (volumeImageIdRequest) {
|
||||
finalRequests.push(volumeImageIdRequest);
|
||||
}
|
||||
@@ -117,31 +115,17 @@ export default function interleaveCenterLoader({
|
||||
const requestType = Enums.RequestType.Prefetch;
|
||||
const priority = 0;
|
||||
|
||||
finalRequests.forEach(
|
||||
({ callLoadImage, additionalDetails, imageId, imageIdIndex, options }) => {
|
||||
const callLoadImageBound = callLoadImage.bind(
|
||||
null,
|
||||
imageId,
|
||||
imageIdIndex,
|
||||
options
|
||||
);
|
||||
finalRequests.forEach(({ callLoadImage, additionalDetails, imageId, imageIdIndex, options }) => {
|
||||
const callLoadImageBound = callLoadImage.bind(null, imageId, imageIdIndex, options);
|
||||
|
||||
imageLoadPoolManager.addRequest(
|
||||
callLoadImageBound,
|
||||
requestType,
|
||||
additionalDetails,
|
||||
priority
|
||||
);
|
||||
}
|
||||
);
|
||||
imageLoadPoolManager.addRequest(callLoadImageBound, requestType, additionalDetails, priority);
|
||||
});
|
||||
|
||||
// clear the volumeIdMapsToLoad
|
||||
volumeIdMapsToLoad.clear();
|
||||
|
||||
// copy the viewportIdVolumeInputArrayMap
|
||||
const viewportIdVolumeInputArrayMapCopy = new Map(
|
||||
viewportIdVolumeInputArrayMap
|
||||
);
|
||||
const viewportIdVolumeInputArrayMapCopy = new Map(viewportIdVolumeInputArrayMap);
|
||||
|
||||
// reset the viewportIdVolumeInputArrayMap
|
||||
viewportIdVolumeInputArrayMap.clear();
|
||||
|
||||
@@ -94,9 +94,7 @@ export default function interleaveTopToBottom({
|
||||
const { imageId } = request;
|
||||
|
||||
AllRequests.forEach(volumeRequests => {
|
||||
const volumeImageIdRequest = volumeRequests.find(
|
||||
req => req.imageId === imageId
|
||||
);
|
||||
const volumeImageIdRequest = volumeRequests.find(req => req.imageId === imageId);
|
||||
if (volumeImageIdRequest) {
|
||||
finalRequests.push(volumeImageIdRequest);
|
||||
}
|
||||
@@ -106,31 +104,17 @@ export default function interleaveTopToBottom({
|
||||
const requestType = Enums.RequestType.Prefetch;
|
||||
const priority = 0;
|
||||
|
||||
finalRequests.forEach(
|
||||
({ callLoadImage, additionalDetails, imageId, imageIdIndex, options }) => {
|
||||
const callLoadImageBound = callLoadImage.bind(
|
||||
null,
|
||||
imageId,
|
||||
imageIdIndex,
|
||||
options
|
||||
);
|
||||
finalRequests.forEach(({ callLoadImage, additionalDetails, imageId, imageIdIndex, options }) => {
|
||||
const callLoadImageBound = callLoadImage.bind(null, imageId, imageIdIndex, options);
|
||||
|
||||
imageLoadPoolManager.addRequest(
|
||||
callLoadImageBound,
|
||||
requestType,
|
||||
additionalDetails,
|
||||
priority
|
||||
);
|
||||
}
|
||||
);
|
||||
imageLoadPoolManager.addRequest(callLoadImageBound, requestType, additionalDetails, priority);
|
||||
});
|
||||
|
||||
// clear the volumeIdMapsToLoad
|
||||
volumeIdMapsToLoad.clear();
|
||||
|
||||
// copy the viewportIdVolumeInputArrayMap
|
||||
const viewportIdVolumeInputArrayMapCopy = new Map(
|
||||
viewportIdVolumeInputArrayMap
|
||||
);
|
||||
const viewportIdVolumeInputArrayMapCopy = new Map(viewportIdVolumeInputArrayMap);
|
||||
|
||||
// reset the viewportIdVolumeInputArrayMap
|
||||
viewportIdVolumeInputArrayMap.clear();
|
||||
|
||||
@@ -32,11 +32,7 @@ const Angle = {
|
||||
throw new Error('Tool not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(
|
||||
const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(
|
||||
referencedImageId,
|
||||
CornerstoneViewportService,
|
||||
viewportId
|
||||
@@ -55,14 +51,10 @@ const Angle = {
|
||||
|
||||
const { points } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(
|
||||
annotation,
|
||||
displaySetService
|
||||
);
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
|
||||
|
||||
const displayText = getDisplayText(mappedAnnotations, displaySet);
|
||||
const getReport = () =>
|
||||
_getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
|
||||
return {
|
||||
uid: annotationUID,
|
||||
@@ -99,16 +91,11 @@ function getMappedAnnotations(annotation, DisplaySetService) {
|
||||
const targetStats = cachedStats[targetId];
|
||||
|
||||
if (!referencedImageId) {
|
||||
throw new Error(
|
||||
'Non-acquisition plane measurement mapping not supported'
|
||||
);
|
||||
throw new Error('Non-acquisition plane measurement mapping not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
frameNumber,
|
||||
} = getSOPInstanceAttributes(referencedImageId);
|
||||
const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =
|
||||
getSOPInstanceAttributes(referencedImageId);
|
||||
|
||||
const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(
|
||||
SOPInstanceUID,
|
||||
@@ -179,17 +166,9 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
||||
const displayText = [];
|
||||
|
||||
// Area is the same for all series
|
||||
const {
|
||||
angle,
|
||||
unit,
|
||||
SeriesNumber,
|
||||
SOPInstanceUID,
|
||||
frameNumber,
|
||||
} = mappedAnnotations[0];
|
||||
const { angle, unit, SeriesNumber, SOPInstanceUID, frameNumber } = mappedAnnotations[0];
|
||||
|
||||
const instance = displaySet.images.find(
|
||||
image => image.SOPInstanceUID === SOPInstanceUID
|
||||
);
|
||||
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
|
||||
|
||||
let InstanceNumber;
|
||||
if (instance) {
|
||||
@@ -202,9 +181,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
||||
return displayText;
|
||||
}
|
||||
const roundedAngle = utils.roundNumber(angle, 2);
|
||||
displayText.push(
|
||||
`${roundedAngle} ${unit} (S: ${SeriesNumber}${instanceText}${frameText})`
|
||||
);
|
||||
displayText.push(`${roundedAngle} ${unit} (S: ${SeriesNumber}${instanceText}${frameText})`);
|
||||
|
||||
return displayText;
|
||||
}
|
||||
|
||||
@@ -31,11 +31,7 @@ const Length = {
|
||||
throw new Error('Tool not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(
|
||||
const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(
|
||||
referencedImageId,
|
||||
cornerstoneViewportService,
|
||||
viewportId
|
||||
@@ -54,10 +50,7 @@ const Length = {
|
||||
|
||||
const { points } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(
|
||||
annotation,
|
||||
displaySetService
|
||||
);
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
|
||||
|
||||
const displayText = getDisplayText(mappedAnnotations, displaySet);
|
||||
|
||||
@@ -91,11 +84,8 @@ function getMappedAnnotations(annotation, displaySetService) {
|
||||
|
||||
const annotations = [];
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
frameNumber,
|
||||
} = getSOPInstanceAttributes(referencedImageId);
|
||||
const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =
|
||||
getSOPInstanceAttributes(referencedImageId);
|
||||
|
||||
const displaySet = displaySetService.getDisplaySetForSOPInstanceUID(
|
||||
SOPInstanceUID,
|
||||
@@ -126,9 +116,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
||||
// Area is the same for all series
|
||||
const { SeriesNumber, SOPInstanceUID, frameNumber } = mappedAnnotations[0];
|
||||
|
||||
const instance = displaySet.images.find(
|
||||
image => image.SOPInstanceUID === SOPInstanceUID
|
||||
);
|
||||
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
|
||||
|
||||
let InstanceNumber;
|
||||
if (instance) {
|
||||
|
||||
@@ -27,11 +27,7 @@ const Bidirectional = {
|
||||
throw new Error('Tool not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(
|
||||
const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(
|
||||
referencedImageId,
|
||||
cornerstoneViewportService,
|
||||
viewportId
|
||||
@@ -50,14 +46,10 @@ const Bidirectional = {
|
||||
|
||||
const { points } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(
|
||||
annotation,
|
||||
displaySetService
|
||||
);
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
|
||||
|
||||
const displayText = getDisplayText(mappedAnnotations, displaySet);
|
||||
const getReport = () =>
|
||||
_getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
|
||||
return {
|
||||
uid: annotationUID,
|
||||
@@ -94,16 +86,11 @@ function getMappedAnnotations(annotation, displaySetService) {
|
||||
const targetStats = cachedStats[targetId];
|
||||
|
||||
if (!referencedImageId) {
|
||||
throw new Error(
|
||||
'Non-acquisition plane measurement mapping not supported'
|
||||
);
|
||||
throw new Error('Non-acquisition plane measurement mapping not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
frameNumber,
|
||||
} = getSOPInstanceAttributes(referencedImageId);
|
||||
const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =
|
||||
getSOPInstanceAttributes(referencedImageId);
|
||||
|
||||
const displaySet = displaySetService.getDisplaySetForSOPInstanceUID(
|
||||
SOPInstanceUID,
|
||||
@@ -175,19 +162,11 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
||||
const displayText = [];
|
||||
|
||||
// Area is the same for all series
|
||||
const {
|
||||
length,
|
||||
width,
|
||||
SeriesNumber,
|
||||
SOPInstanceUID,
|
||||
frameNumber,
|
||||
} = mappedAnnotations[0];
|
||||
const { length, width, SeriesNumber, SOPInstanceUID, frameNumber } = mappedAnnotations[0];
|
||||
const roundedLength = utils.roundNumber(length, 2);
|
||||
const roundedWidth = utils.roundNumber(width, 2);
|
||||
|
||||
const instance = displaySet.images.find(
|
||||
image => image.SOPInstanceUID === SOPInstanceUID
|
||||
);
|
||||
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
|
||||
|
||||
let InstanceNumber;
|
||||
if (instance) {
|
||||
@@ -197,9 +176,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
||||
const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';
|
||||
const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';
|
||||
|
||||
displayText.push(
|
||||
`L: ${roundedLength} mm (S: ${SeriesNumber}${instanceText}${frameText})`
|
||||
);
|
||||
displayText.push(`L: ${roundedLength} mm (S: ${SeriesNumber}${instanceText}${frameText})`);
|
||||
displayText.push(`W: ${roundedWidth} mm`);
|
||||
|
||||
return displayText;
|
||||
|
||||
@@ -25,11 +25,7 @@ const CircleROI = {
|
||||
throw new Error('Tool not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(
|
||||
const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(
|
||||
referencedImageId,
|
||||
CornerstoneViewportService,
|
||||
viewportId
|
||||
@@ -48,14 +44,10 @@ const CircleROI = {
|
||||
|
||||
const { points } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(
|
||||
annotation,
|
||||
DisplaySetService
|
||||
);
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);
|
||||
|
||||
const displayText = getDisplayText(mappedAnnotations, displaySet);
|
||||
const getReport = () =>
|
||||
_getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
|
||||
return {
|
||||
uid: annotationUID,
|
||||
@@ -93,16 +85,11 @@ function getMappedAnnotations(annotation, DisplaySetService) {
|
||||
|
||||
if (!referencedImageId) {
|
||||
// Todo: Non-acquisition plane measurement mapping not supported yet
|
||||
throw new Error(
|
||||
'Non-acquisition plane measurement mapping not supported'
|
||||
);
|
||||
throw new Error('Non-acquisition plane measurement mapping not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
frameNumber,
|
||||
} = getSOPInstanceAttributes(referencedImageId);
|
||||
const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =
|
||||
getSOPInstanceAttributes(referencedImageId);
|
||||
|
||||
const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(
|
||||
SOPInstanceUID,
|
||||
@@ -150,12 +137,7 @@ function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
|
||||
return;
|
||||
}
|
||||
|
||||
columns.push(
|
||||
`max (${unit})`,
|
||||
`mean (${unit})`,
|
||||
`std (${unit})`,
|
||||
`area (mm2)`
|
||||
);
|
||||
columns.push(`max (${unit})`, `mean (${unit})`, `std (${unit})`, `area (mm2)`);
|
||||
values.push(max, mean, stdDev, area);
|
||||
});
|
||||
|
||||
@@ -188,9 +170,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
||||
// Area is the same for all series
|
||||
const { area, SOPInstanceUID, frameNumber } = mappedAnnotations[0];
|
||||
|
||||
const instance = displaySet.images.find(
|
||||
image => image.SOPInstanceUID === SOPInstanceUID
|
||||
);
|
||||
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
|
||||
|
||||
let InstanceNumber;
|
||||
if (instance) {
|
||||
|
||||
@@ -32,11 +32,7 @@ const CobbAngle = {
|
||||
throw new Error('Tool not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(
|
||||
const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(
|
||||
referencedImageId,
|
||||
CornerstoneViewportService,
|
||||
viewportId
|
||||
@@ -55,14 +51,10 @@ const CobbAngle = {
|
||||
|
||||
const { points } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(
|
||||
annotation,
|
||||
displaySetService
|
||||
);
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
|
||||
|
||||
const displayText = getDisplayText(mappedAnnotations, displaySet);
|
||||
const getReport = () =>
|
||||
_getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
|
||||
return {
|
||||
uid: annotationUID,
|
||||
@@ -99,16 +91,11 @@ function getMappedAnnotations(annotation, DisplaySetService) {
|
||||
const targetStats = cachedStats[targetId];
|
||||
|
||||
if (!referencedImageId) {
|
||||
throw new Error(
|
||||
'Non-acquisition plane measurement mapping not supported'
|
||||
);
|
||||
throw new Error('Non-acquisition plane measurement mapping not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
frameNumber,
|
||||
} = getSOPInstanceAttributes(referencedImageId);
|
||||
const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =
|
||||
getSOPInstanceAttributes(referencedImageId);
|
||||
|
||||
const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(
|
||||
SOPInstanceUID,
|
||||
@@ -179,17 +166,9 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
||||
const displayText = [];
|
||||
|
||||
// Area is the same for all series
|
||||
const {
|
||||
angle,
|
||||
unit,
|
||||
SeriesNumber,
|
||||
SOPInstanceUID,
|
||||
frameNumber,
|
||||
} = mappedAnnotations[0];
|
||||
const { angle, unit, SeriesNumber, SOPInstanceUID, frameNumber } = mappedAnnotations[0];
|
||||
|
||||
const instance = displaySet.images.find(
|
||||
image => image.SOPInstanceUID === SOPInstanceUID
|
||||
);
|
||||
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
|
||||
|
||||
let InstanceNumber;
|
||||
if (instance) {
|
||||
@@ -202,9 +181,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
||||
return displayText;
|
||||
}
|
||||
const roundedAngle = utils.roundNumber(angle, 2);
|
||||
displayText.push(
|
||||
`${roundedAngle} ${unit} (S: ${SeriesNumber}${instanceText}${frameText})`
|
||||
);
|
||||
displayText.push(`${roundedAngle} ${unit} (S: ${SeriesNumber}${instanceText}${frameText})`);
|
||||
|
||||
return displayText;
|
||||
}
|
||||
|
||||
@@ -25,11 +25,7 @@ const EllipticalROI = {
|
||||
throw new Error('Tool not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(
|
||||
const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(
|
||||
referencedImageId,
|
||||
cornerstoneViewportService,
|
||||
viewportId
|
||||
@@ -48,14 +44,10 @@ const EllipticalROI = {
|
||||
|
||||
const { points } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(
|
||||
annotation,
|
||||
displaySetService
|
||||
);
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
|
||||
|
||||
const displayText = getDisplayText(mappedAnnotations, displaySet);
|
||||
const getReport = () =>
|
||||
_getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
|
||||
return {
|
||||
uid: annotationUID,
|
||||
@@ -93,16 +85,11 @@ function getMappedAnnotations(annotation, displaySetService) {
|
||||
|
||||
if (!referencedImageId) {
|
||||
// Todo: Non-acquisition plane measurement mapping not supported yet
|
||||
throw new Error(
|
||||
'Non-acquisition plane measurement mapping not supported'
|
||||
);
|
||||
throw new Error('Non-acquisition plane measurement mapping not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
frameNumber,
|
||||
} = getSOPInstanceAttributes(referencedImageId);
|
||||
const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =
|
||||
getSOPInstanceAttributes(referencedImageId);
|
||||
|
||||
const displaySet = displaySetService.getDisplaySetForSOPInstanceUID(
|
||||
SOPInstanceUID,
|
||||
@@ -150,12 +137,7 @@ function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
|
||||
return;
|
||||
}
|
||||
|
||||
columns.push(
|
||||
`max (${unit})`,
|
||||
`mean (${unit})`,
|
||||
`std (${unit})`,
|
||||
`area (mm2)`
|
||||
);
|
||||
columns.push(`max (${unit})`, `mean (${unit})`, `std (${unit})`, `area (mm2)`);
|
||||
values.push(max, mean, stdDev, area);
|
||||
});
|
||||
|
||||
@@ -188,9 +170,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
||||
// Area is the same for all series
|
||||
const { area, SOPInstanceUID, frameNumber } = mappedAnnotations[0];
|
||||
|
||||
const instance = displaySet.images.find(
|
||||
image => image.SOPInstanceUID === SOPInstanceUID
|
||||
);
|
||||
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
|
||||
|
||||
let InstanceNumber;
|
||||
if (instance) {
|
||||
|
||||
@@ -32,11 +32,7 @@ const Length = {
|
||||
throw new Error('Tool not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(
|
||||
const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(
|
||||
referencedImageId,
|
||||
cornerstoneViewportService,
|
||||
viewportId
|
||||
@@ -55,14 +51,10 @@ const Length = {
|
||||
|
||||
const { points } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(
|
||||
annotation,
|
||||
displaySetService
|
||||
);
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
|
||||
|
||||
const displayText = getDisplayText(mappedAnnotations, displaySet);
|
||||
const getReport = () =>
|
||||
_getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
|
||||
return {
|
||||
uid: annotationUID,
|
||||
@@ -99,16 +91,11 @@ function getMappedAnnotations(annotation, displaySetService) {
|
||||
const targetStats = cachedStats[targetId];
|
||||
|
||||
if (!referencedImageId) {
|
||||
throw new Error(
|
||||
'Non-acquisition plane measurement mapping not supported'
|
||||
);
|
||||
throw new Error('Non-acquisition plane measurement mapping not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
frameNumber,
|
||||
} = getSOPInstanceAttributes(referencedImageId);
|
||||
const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =
|
||||
getSOPInstanceAttributes(referencedImageId);
|
||||
|
||||
const displaySet = displaySetService.getDisplaySetForSOPInstanceUID(
|
||||
SOPInstanceUID,
|
||||
@@ -179,16 +166,9 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
||||
const displayText = [];
|
||||
|
||||
// Area is the same for all series
|
||||
const {
|
||||
length,
|
||||
SeriesNumber,
|
||||
SOPInstanceUID,
|
||||
frameNumber,
|
||||
} = mappedAnnotations[0];
|
||||
const { length, SeriesNumber, SOPInstanceUID, frameNumber } = mappedAnnotations[0];
|
||||
|
||||
const instance = displaySet.images.find(
|
||||
image => image.SOPInstanceUID === SOPInstanceUID
|
||||
);
|
||||
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
|
||||
|
||||
let InstanceNumber;
|
||||
if (instance) {
|
||||
@@ -202,9 +182,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
||||
return displayText;
|
||||
}
|
||||
const roundedLength = utils.roundNumber(length, 2);
|
||||
displayText.push(
|
||||
`${roundedLength} mm (S: ${SeriesNumber}${instanceText}${frameText})`
|
||||
);
|
||||
displayText.push(`${roundedLength} mm (S: ${SeriesNumber}${instanceText}${frameText})`);
|
||||
|
||||
return displayText;
|
||||
}
|
||||
|
||||
@@ -31,11 +31,7 @@ const PlanarFreehandROI = {
|
||||
throw new Error('Tool not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(
|
||||
const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(
|
||||
referencedImageId,
|
||||
CornerstoneViewportService,
|
||||
viewportId
|
||||
@@ -54,14 +50,10 @@ const PlanarFreehandROI = {
|
||||
|
||||
const { points } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(
|
||||
annotation,
|
||||
DisplaySetService
|
||||
);
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);
|
||||
|
||||
const displayText = getDisplayText(mappedAnnotations);
|
||||
const getReport = () =>
|
||||
_getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
|
||||
return {
|
||||
uid: annotationUID,
|
||||
@@ -96,10 +88,8 @@ function getMappedAnnotations(annotationData, DisplaySetService) {
|
||||
|
||||
const annotations = [];
|
||||
|
||||
const {
|
||||
SOPInstanceUID: _SOPInstanceUID,
|
||||
SeriesInstanceUID: _SeriesInstanceUID,
|
||||
} = getSOPInstanceAttributes(referencedImageId) || {};
|
||||
const { SOPInstanceUID: _SOPInstanceUID, SeriesInstanceUID: _SeriesInstanceUID } =
|
||||
getSOPInstanceAttributes(referencedImageId) || {};
|
||||
|
||||
if (!_SOPInstanceUID || !_SeriesInstanceUID) {
|
||||
return annotations;
|
||||
|
||||
@@ -25,11 +25,7 @@ const RectangleROI = {
|
||||
throw new Error('Tool not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(
|
||||
const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(
|
||||
referencedImageId,
|
||||
CornerstoneViewportService,
|
||||
viewportId
|
||||
@@ -48,14 +44,10 @@ const RectangleROI = {
|
||||
|
||||
const { points } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(
|
||||
annotation,
|
||||
DisplaySetService
|
||||
);
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);
|
||||
|
||||
const displayText = getDisplayText(mappedAnnotations, displaySet);
|
||||
const getReport = () =>
|
||||
_getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
const getReport = () => _getReport(mappedAnnotations, points, FrameOfReferenceUID);
|
||||
|
||||
return {
|
||||
uid: annotationUID,
|
||||
@@ -93,16 +85,11 @@ function getMappedAnnotations(annotation, DisplaySetService) {
|
||||
|
||||
if (!referencedImageId) {
|
||||
// Todo: Non-acquisition plane measurement mapping not supported yet
|
||||
throw new Error(
|
||||
'Non-acquisition plane measurement mapping not supported'
|
||||
);
|
||||
throw new Error('Non-acquisition plane measurement mapping not supported');
|
||||
}
|
||||
|
||||
const {
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
frameNumber,
|
||||
} = getSOPInstanceAttributes(referencedImageId);
|
||||
const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =
|
||||
getSOPInstanceAttributes(referencedImageId);
|
||||
|
||||
const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(
|
||||
SOPInstanceUID,
|
||||
@@ -150,12 +137,7 @@ function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
|
||||
return;
|
||||
}
|
||||
|
||||
columns.push(
|
||||
`max (${unit})`,
|
||||
`mean (${unit})`,
|
||||
`std (${unit})`,
|
||||
`area (mm2)`
|
||||
);
|
||||
columns.push(`max (${unit})`, `mean (${unit})`, `std (${unit})`, `area (mm2)`);
|
||||
values.push(max, mean, stdDev, area);
|
||||
});
|
||||
|
||||
@@ -188,9 +170,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
||||
// Area is the same for all series
|
||||
const { area, SOPInstanceUID, frameNumber } = mappedAnnotations[0];
|
||||
|
||||
const instance = displaySet.images.find(
|
||||
image => image.SOPInstanceUID === SOPInstanceUID
|
||||
);
|
||||
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
|
||||
|
||||
let InstanceNumber;
|
||||
if (instance) {
|
||||
|
||||
+2
-9
@@ -23,15 +23,8 @@ const measurementServiceMappingsFactory = (
|
||||
*/
|
||||
|
||||
const _getValueTypeFromToolType = toolType => {
|
||||
const {
|
||||
POLYLINE,
|
||||
ELLIPSE,
|
||||
CIRCLE,
|
||||
RECTANGLE,
|
||||
BIDIRECTIONAL,
|
||||
POINT,
|
||||
ANGLE,
|
||||
} = MeasurementService.VALUE_TYPES;
|
||||
const { POLYLINE, ELLIPSE, CIRCLE, RECTANGLE, BIDIRECTIONAL, POINT, ANGLE } =
|
||||
MeasurementService.VALUE_TYPES;
|
||||
|
||||
// TODO -> I get why this was attempted, but its not nearly flexible enough.
|
||||
// A single measurement may have an ellipse + a bidirectional measurement, for instances.
|
||||
|
||||
@@ -18,24 +18,16 @@ function setAnnotationSelected(annotationUID: string, selected: boolean): void {
|
||||
const isCurrentSelected = isAnnotationSelected(annotationUID);
|
||||
// branch cut, avoid invoking imaging library unnecessarily.
|
||||
if (isCurrentSelected !== selected) {
|
||||
cs3dToolAnnotationUtils.selection.setAnnotationSelected(
|
||||
annotationUID,
|
||||
selected
|
||||
);
|
||||
cs3dToolAnnotationUtils.selection.setAnnotationSelected(annotationUID, selected);
|
||||
}
|
||||
}
|
||||
|
||||
function getFirstAnnotationSelected(element) {
|
||||
const [selectedAnnotationUID] =
|
||||
cs3dToolAnnotationUtils.selection.getAnnotationsSelected() || [];
|
||||
const [selectedAnnotationUID] = cs3dToolAnnotationUtils.selection.getAnnotationsSelected() || [];
|
||||
|
||||
if (selectedAnnotationUID) {
|
||||
return cs3dToolAnnotationUtils.state.getAnnotation(selectedAnnotationUID);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
isAnnotationSelected,
|
||||
setAnnotationSelected,
|
||||
getFirstAnnotationSelected,
|
||||
};
|
||||
export { isAnnotationSelected, setAnnotationSelected, getFirstAnnotationSelected };
|
||||
@@ -51,9 +51,7 @@ export default function interleaveNthLoader({
|
||||
.map(volume => volume.getImageLoadRequests())
|
||||
.filter(requests => requests?.[0]?.imageId);
|
||||
|
||||
const orderedRequests = originalRequests.map(request =>
|
||||
getNthFrames(request)
|
||||
);
|
||||
const orderedRequests = originalRequests.map(request => getNthFrames(request));
|
||||
|
||||
// set the finalRequests to the imageLoadPoolManager
|
||||
const finalRequests = interleave(orderedRequests);
|
||||
@@ -61,31 +59,17 @@ export default function interleaveNthLoader({
|
||||
const requestType = Enums.RequestType.Prefetch;
|
||||
const priority = 0;
|
||||
|
||||
finalRequests.forEach(
|
||||
({ callLoadImage, additionalDetails, imageId, imageIdIndex, options }) => {
|
||||
const callLoadImageBound = callLoadImage.bind(
|
||||
null,
|
||||
imageId,
|
||||
imageIdIndex,
|
||||
options
|
||||
);
|
||||
finalRequests.forEach(({ callLoadImage, additionalDetails, imageId, imageIdIndex, options }) => {
|
||||
const callLoadImageBound = callLoadImage.bind(null, imageId, imageIdIndex, options);
|
||||
|
||||
imageLoadPoolManager.addRequest(
|
||||
callLoadImageBound,
|
||||
requestType,
|
||||
additionalDetails,
|
||||
priority
|
||||
);
|
||||
}
|
||||
);
|
||||
imageLoadPoolManager.addRequest(callLoadImageBound, requestType, additionalDetails, priority);
|
||||
});
|
||||
|
||||
// clear the volumeIdMapsToLoad
|
||||
volumeIdMapsToLoad.clear();
|
||||
|
||||
// copy the viewportIdVolumeInputArrayMap
|
||||
const viewportIdVolumeInputArrayMapCopy = new Map(
|
||||
viewportIdVolumeInputArrayMap
|
||||
);
|
||||
const viewportIdVolumeInputArrayMapCopy = new Map(viewportIdVolumeInputArrayMap);
|
||||
|
||||
// reset the viewportIdVolumeInputArrayMap
|
||||
viewportIdVolumeInputArrayMap.clear();
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { segmentation } from '@cornerstonejs/tools';
|
||||
|
||||
function removeToolGroupSegmentationRepresentations(toolGroupId) {
|
||||
const representations = segmentation.state.getSegmentationRepresentations(
|
||||
toolGroupId
|
||||
);
|
||||
const representations = segmentation.state.getSegmentationRepresentations(toolGroupId);
|
||||
|
||||
if (!representations || !representations.length) {
|
||||
return;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { Types, getRenderingEngine, utilities } from '@cornerstonejs/core';
|
||||
|
||||
export default function calculateViewportRegistrations(
|
||||
viewports: Types.IViewportId[]
|
||||
) {
|
||||
export default function calculateViewportRegistrations(viewports: Types.IViewportId[]) {
|
||||
const viewportPairs = _getViewportPairs(viewports);
|
||||
|
||||
for (const [viewport, nextViewport] of viewportPairs) {
|
||||
|
||||
@@ -6,28 +6,16 @@ import calculateViewportRegistrations from './calculateViewportRegistrations';
|
||||
// ]}
|
||||
let STACK_IMAGE_SYNC_GROUPS_INFO = [];
|
||||
|
||||
export default function toggleStackImageSync({
|
||||
toggledState,
|
||||
servicesManager,
|
||||
getEnabledElement,
|
||||
}) {
|
||||
const {
|
||||
syncGroupService,
|
||||
viewportGridService,
|
||||
displaySetService,
|
||||
cornerstoneViewportService,
|
||||
} = servicesManager.services;
|
||||
export default function toggleStackImageSync({ toggledState, servicesManager, getEnabledElement }) {
|
||||
const { syncGroupService, viewportGridService, displaySetService, cornerstoneViewportService } =
|
||||
servicesManager.services;
|
||||
|
||||
if (!toggledState) {
|
||||
STACK_IMAGE_SYNC_GROUPS_INFO.forEach(syncGroupInfo => {
|
||||
const { viewports, synchronizerId } = syncGroupInfo;
|
||||
|
||||
viewports.forEach(({ viewportId, renderingEngineId }) => {
|
||||
syncGroupService.removeViewportFromSyncGroup(
|
||||
viewportId,
|
||||
renderingEngineId,
|
||||
synchronizerId
|
||||
);
|
||||
syncGroupService.removeViewportFromSyncGroup(viewportId, renderingEngineId, synchronizerId);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -47,9 +35,7 @@ export default function toggleStackImageSync({
|
||||
const { displaySetInstanceUIDs } = viewport;
|
||||
|
||||
for (const displaySetInstanceUID of displaySetInstanceUIDs) {
|
||||
const displaySet = displaySetService.getDisplaySetByUID(
|
||||
displaySetInstanceUID
|
||||
);
|
||||
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||
|
||||
return !!displaySet?.isReconstructable;
|
||||
}
|
||||
@@ -64,8 +50,7 @@ export default function toggleStackImageSync({
|
||||
}
|
||||
|
||||
const { element } = cornerstoneViewportService.getViewportInfo(viewportId);
|
||||
const { viewport: csViewport, renderingEngineId } =
|
||||
getEnabledElement(element);
|
||||
const { viewport: csViewport, renderingEngineId } = getEnabledElement(element);
|
||||
const { viewPlaneNormal } = csViewport.getCamera();
|
||||
|
||||
// Should we round here? I guess so, but not sure how much precision we need
|
||||
@@ -82,9 +67,7 @@ export default function toggleStackImageSync({
|
||||
|
||||
// create synchronizer for each group
|
||||
Object.values(viewportsByOrientation).map(viewports => {
|
||||
let synchronizerId = viewports
|
||||
.map(({ viewportId }) => viewportId)
|
||||
.join(',');
|
||||
let synchronizerId = viewports.map(({ viewportId }) => viewportId).join(',');
|
||||
|
||||
synchronizerId = `imageSync_${synchronizerId}`;
|
||||
|
||||
|
||||
Reference in new issue
Block a user