fix(toolbox): Preserve user-specified tool state and streamline command execution (#4063)
This commit is contained in:
parent
4784638717
commit
f1a736d193
@ -47,7 +47,7 @@ provided by the <a href="https://ohif.org/">Open Health Imaging Foundation (OHIF
|
|||||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-volume-rendering.webp?raw=true" alt="Volume Rendering" width="350"/> | Volume Rendering | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&hangingprotocolId=mprAnd3DVolumeViewport) |
|
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-volume-rendering.webp?raw=true" alt="Volume Rendering" width="350"/> | Volume Rendering | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&hangingprotocolId=mprAnd3DVolumeViewport) |
|
||||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-pdf.webp?raw=true" alt="PDF" width="350"/> | PDF | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.317377619501274872606137091638706705333) |
|
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-pdf.webp?raw=true" alt="PDF" width="350"/> | PDF | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.317377619501274872606137091638706705333) |
|
||||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-rtstruct.webp?raw=true" alt="RTSTRUCT" width="350"/> | RT STRUCT | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0) |
|
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-rtstruct.webp?raw=true" alt="RTSTRUCT" width="350"/> | RT STRUCT | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0) |
|
||||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-4D.webp?raw=true" alt="4D" width="350"/> | 4D | [Demo](https://viewer.ohif.org/dynamic-volume?StudyInstanceUIDs=2.25.232704420736447710317909004159492840763) |
|
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-4d.webp?raw=true" alt="4D" width="350"/> | 4D | [Demo](https://viewer.ohif.org/dynamic-volume?StudyInstanceUIDs=2.25.232704420736447710317909004159492840763) |
|
||||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-video.webp?raw=true" alt="VIDEO" width="350"/> | Video | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.96975534054447904995905761963464388233) |
|
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-video.webp?raw=true" alt="VIDEO" width="350"/> | Video | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.96975534054447904995905761963464388233) |
|
||||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/microscopy.webp?raw=true" alt="microscopy" width="350"/> | Slide Microscopy | [Demo](https://viewer.ohif.org/microscopy?StudyInstanceUIDs=2.25.141277760791347900862109212450152067508) |
|
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/microscopy.webp?raw=true" alt="microscopy" width="350"/> | Slide Microscopy | [Demo](https://viewer.ohif.org/microscopy?StudyInstanceUIDs=2.25.141277760791347900862109212450152067508) |
|
||||||
|
|
||||||
|
|||||||
@ -46,9 +46,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/adapters": "^1.70.13",
|
"@cornerstonejs/adapters": "^1.70.14",
|
||||||
"@cornerstonejs/core": "^1.70.13",
|
"@cornerstonejs/core": "^1.70.14",
|
||||||
"@kitware/vtk.js": "30.3.3",
|
"@kitware/vtk.js": "30.4.1",
|
||||||
"react-color": "^2.19.3"
|
"react-color": "^2.19.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
export function getToolbarModule({ commandsManager, servicesManager }) {
|
export function getToolbarModule({ servicesManager }) {
|
||||||
const { segmentationService, toolGroupService } = servicesManager.services;
|
const { segmentationService, toolbarService, toolGroupService } = servicesManager.services;
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: 'evaluate.cornerstone.segmentation',
|
name: 'evaluate.cornerstone.segmentation',
|
||||||
@ -20,12 +20,16 @@ export function getToolbarModule({ commandsManager, servicesManager }) {
|
|||||||
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
|
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
|
||||||
|
|
||||||
if (!toolGroup) {
|
if (!toolGroup) {
|
||||||
return;
|
return {
|
||||||
|
disabled: true,
|
||||||
|
className: '!text-common-bright ohif-disabled',
|
||||||
|
disabledText: disabledText ?? 'Not available on the current viewport',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const toolName = getToolNameForButton(button);
|
const toolName = toolbarService.getToolNameForButton(button);
|
||||||
|
|
||||||
if (!toolGroup || !toolGroup.hasTool(toolName)) {
|
if (!toolGroup.hasTool(toolName) && !toolNames) {
|
||||||
return {
|
return {
|
||||||
disabled: true,
|
disabled: true,
|
||||||
className: '!text-common-bright ohif-disabled',
|
className: '!text-common-bright ohif-disabled',
|
||||||
@ -51,19 +55,3 @@ export function getToolbarModule({ commandsManager, servicesManager }) {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo: this is duplicate, we should move it to a shared location
|
|
||||||
function getToolNameForButton(button) {
|
|
||||||
const { props } = button;
|
|
||||||
|
|
||||||
const commands = props?.commands || button.commands;
|
|
||||||
const commandsArray = Array.isArray(commands) ? commands : [commands];
|
|
||||||
const firstCommand = commandsArray[0];
|
|
||||||
|
|
||||||
if (firstCommand?.commandOptions) {
|
|
||||||
return firstCommand.commandOptions.toolName ?? props?.id ?? button.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// use id as a fallback for toolName
|
|
||||||
return props?.id ?? button.id;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -46,9 +46,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/adapters": "^1.70.13",
|
"@cornerstonejs/adapters": "^1.70.14",
|
||||||
"@cornerstonejs/core": "^1.70.13",
|
"@cornerstonejs/core": "^1.70.14",
|
||||||
"@cornerstonejs/tools": "^1.70.13",
|
"@cornerstonejs/tools": "^1.70.14",
|
||||||
"classnames": "^2.3.2"
|
"classnames": "^2.3.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,9 +42,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/core": "^1.70.13",
|
"@cornerstonejs/core": "^1.70.14",
|
||||||
"@cornerstonejs/streaming-image-volume-loader": "^1.70.13",
|
"@cornerstonejs/streaming-image-volume-loader": "^1.70.14",
|
||||||
"@cornerstonejs/tools": "^1.70.13",
|
"@cornerstonejs/tools": "^1.70.14",
|
||||||
"classnames": "^2.3.2"
|
"classnames": "^2.3.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,7 +38,7 @@
|
|||||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||||
"@cornerstonejs/codec-openjpeg": "^1.2.2",
|
"@cornerstonejs/codec-openjpeg": "^1.2.2",
|
||||||
"@cornerstonejs/codec-openjph": "^2.4.2",
|
"@cornerstonejs/codec-openjph": "^2.4.2",
|
||||||
"@cornerstonejs/dicom-image-loader": "^1.70.13",
|
"@cornerstonejs/dicom-image-loader": "^1.70.14",
|
||||||
"@icr/polyseg-wasm": "^0.4.0",
|
"@icr/polyseg-wasm": "^0.4.0",
|
||||||
"@ohif/core": "3.8.0-beta.92",
|
"@ohif/core": "3.8.0-beta.92",
|
||||||
"@ohif/ui": "3.8.0-beta.92",
|
"@ohif/ui": "3.8.0-beta.92",
|
||||||
@ -55,12 +55,12 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@cornerstonejs/adapters": "^1.70.13",
|
"@cornerstonejs/adapters": "^1.70.14",
|
||||||
"@cornerstonejs/core": "^1.70.13",
|
"@cornerstonejs/core": "^1.70.14",
|
||||||
"@cornerstonejs/streaming-image-volume-loader": "^1.70.13",
|
"@cornerstonejs/streaming-image-volume-loader": "^1.70.14",
|
||||||
"@cornerstonejs/tools": "^1.70.13",
|
"@cornerstonejs/tools": "^1.70.14",
|
||||||
"@icr/polyseg-wasm": "^0.4.0",
|
"@icr/polyseg-wasm": "^0.4.0",
|
||||||
"@kitware/vtk.js": "30.3.3",
|
"@kitware/vtk.js": "30.4.1",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
"lodash.debounce": "4.0.8",
|
"lodash.debounce": "4.0.8",
|
||||||
"lodash.merge": "^4.6.2",
|
"lodash.merge": "^4.6.2",
|
||||||
|
|||||||
@ -485,7 +485,10 @@ function _subscribeToJumpToMeasurementEvents(
|
|||||||
cornerstoneViewportService.getViewportIdToJump(
|
cornerstoneViewportService.getViewportIdToJump(
|
||||||
jumpId,
|
jumpId,
|
||||||
measurement.displaySetInstanceUID,
|
measurement.displaySetInstanceUID,
|
||||||
{ referencedImageId: measurement.referencedImageId }
|
{
|
||||||
|
referencedImageId:
|
||||||
|
measurement.referencedImageId || measurement.metadata?.referencedImageId,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (cacheJumpToMeasurementEvent.cornerstoneViewport !== viewportId) {
|
if (cacheJumpToMeasurementEvent.cornerstoneViewport !== viewportId) {
|
||||||
@ -594,6 +597,9 @@ function _jumpToMeasurement(
|
|||||||
i => i.SOPInstanceUID === SOPInstanceUID
|
i => i.SOPInstanceUID === SOPInstanceUID
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// the index is reversed in the volume viewport
|
||||||
|
// imageIdIndex = referencedDisplaySet.images.length - 1 - imageIdIndex;
|
||||||
|
|
||||||
const { viewPlaneNormal: viewportViewPlane } = viewport.getCamera();
|
const { viewPlaneNormal: viewportViewPlane } = viewport.getCamera();
|
||||||
|
|
||||||
// should compare abs for both planes since the direction can be flipped
|
// should compare abs for both planes since the direction can be flipped
|
||||||
|
|||||||
@ -23,7 +23,7 @@ function CornerstoneImageScrollbar({
|
|||||||
|
|
||||||
if (isCineEnabled) {
|
if (isCineEnabled) {
|
||||||
// on image scrollbar change, stop the CINE if it is playing
|
// on image scrollbar change, stop the CINE if it is playing
|
||||||
cineService.stopClip(element);
|
cineService.stopClip(element, { viewportId });
|
||||||
cineService.setCine({ id: viewportId, isPlaying: false });
|
cineService.setCine({ id: viewportId, isPlaying: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -66,7 +66,7 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
|
|||||||
}
|
}
|
||||||
cineService.setCine({ id: viewportId, isPlaying, frameRate });
|
cineService.setCine({ id: viewportId, isPlaying, frameRate });
|
||||||
setNewStackFrameRate(frameRate);
|
setNewStackFrameRate(frameRate);
|
||||||
}, [displaySetService, viewportId, viewportGridService, cines, isCineEnabled]);
|
}, [displaySetService, viewportId, viewportGridService, cines, isCineEnabled, enabledVPElement]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
isMountedRef.current = true;
|
isMountedRef.current = true;
|
||||||
@ -78,6 +78,14 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
|
|||||||
};
|
};
|
||||||
}, [isCineEnabled, newDisplaySetHandler]);
|
}, [isCineEnabled, newDisplaySetHandler]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isCineEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cineHandler();
|
||||||
|
}, [isCineEnabled, cineHandler, enabledVPElement]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use effect for handling new display set
|
* Use effect for handling new display set
|
||||||
*/
|
*/
|
||||||
@ -112,7 +120,7 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
|
|||||||
cineHandler();
|
cineHandler();
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
cineService.stopClip(enabledVPElement);
|
cineService.stopClip(enabledVPElement, { viewportId });
|
||||||
};
|
};
|
||||||
}, [cines, viewportId, cineService, enabledVPElement, cineHandler]);
|
}, [cines, viewportId, cineService, enabledVPElement, cineHandler]);
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ const getToggledClassName = (isToggled: boolean) => {
|
|||||||
export default function getToolbarModule({ commandsManager, servicesManager }) {
|
export default function getToolbarModule({ commandsManager, servicesManager }) {
|
||||||
const {
|
const {
|
||||||
toolGroupService,
|
toolGroupService,
|
||||||
|
toolbarService,
|
||||||
syncGroupService,
|
syncGroupService,
|
||||||
cornerstoneViewportService,
|
cornerstoneViewportService,
|
||||||
hangingProtocolService,
|
hangingProtocolService,
|
||||||
@ -21,16 +22,16 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
|
|||||||
// enabled or not
|
// enabled or not
|
||||||
{
|
{
|
||||||
name: 'evaluate.cornerstoneTool',
|
name: 'evaluate.cornerstoneTool',
|
||||||
evaluate: ({ viewportId, button, disabledText }) => {
|
evaluate: ({ viewportId, button, toolNames, disabledText }) => {
|
||||||
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
|
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
|
||||||
|
|
||||||
if (!toolGroup) {
|
if (!toolGroup) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const toolName = getToolNameForButton(button);
|
const toolName = toolbarService.getToolNameForButton(button);
|
||||||
|
|
||||||
if (!toolGroup || !toolGroup.hasTool(toolName)) {
|
if (!toolGroup || (!toolGroup.hasTool(toolName) && !toolNames)) {
|
||||||
return {
|
return {
|
||||||
disabled: true,
|
disabled: true,
|
||||||
className: '!text-common-bright ohif-disabled',
|
className: '!text-common-bright ohif-disabled',
|
||||||
@ -38,7 +39,9 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const isPrimaryActive = toolGroup.getActivePrimaryMouseButtonTool() === toolName;
|
const isPrimaryActive = toolNames
|
||||||
|
? toolNames.includes(toolGroup.getActivePrimaryMouseButtonTool())
|
||||||
|
: toolGroup.getActivePrimaryMouseButtonTool() === toolName;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
@ -71,7 +74,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
|
|||||||
// check if the active toolName is part of the items then we need
|
// check if the active toolName is part of the items then we need
|
||||||
// to move it to the primary button
|
// to move it to the primary button
|
||||||
const activeToolIndex = items.findIndex(item => {
|
const activeToolIndex = items.findIndex(item => {
|
||||||
const toolName = getToolNameForButton(item);
|
const toolName = toolbarService.getToolNameForButton(item);
|
||||||
return toolName === activeToolName;
|
return toolName === activeToolName;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -114,6 +117,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
|
|||||||
_evaluateToggle({
|
_evaluateToggle({
|
||||||
viewportId,
|
viewportId,
|
||||||
button,
|
button,
|
||||||
|
toolbarService,
|
||||||
disabledText,
|
disabledText,
|
||||||
offModes: [Enums.ToolModes.Disabled],
|
offModes: [Enums.ToolModes.Disabled],
|
||||||
toolGroupService,
|
toolGroupService,
|
||||||
@ -125,6 +129,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
|
|||||||
_evaluateToggle({
|
_evaluateToggle({
|
||||||
viewportId,
|
viewportId,
|
||||||
button,
|
button,
|
||||||
|
toolbarService,
|
||||||
disabledText,
|
disabledText,
|
||||||
offModes: [Enums.ToolModes.Disabled, Enums.ToolModes.Passive],
|
offModes: [Enums.ToolModes.Disabled, Enums.ToolModes.Passive],
|
||||||
toolGroupService,
|
toolGroupService,
|
||||||
@ -267,13 +272,20 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function _evaluateToggle({ viewportId, button, disabledText, offModes, toolGroupService }) {
|
function _evaluateToggle({
|
||||||
|
viewportId,
|
||||||
|
toolbarService,
|
||||||
|
button,
|
||||||
|
disabledText,
|
||||||
|
offModes,
|
||||||
|
toolGroupService,
|
||||||
|
}) {
|
||||||
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
|
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
|
||||||
|
|
||||||
if (!toolGroup) {
|
if (!toolGroup) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const toolName = getToolNameForButton(button);
|
const toolName = toolbarService.getToolNameForButton(button);
|
||||||
|
|
||||||
if (!toolGroup.hasTool(toolName)) {
|
if (!toolGroup.hasTool(toolName)) {
|
||||||
return {
|
return {
|
||||||
@ -289,19 +301,3 @@ function _evaluateToggle({ viewportId, button, disabledText, offModes, toolGroup
|
|||||||
className: getToggledClassName(!isOff),
|
className: getToggledClassName(!isOff),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo: this is duplicate, we should move it to a shared location
|
|
||||||
function getToolNameForButton(button) {
|
|
||||||
const { props } = button;
|
|
||||||
|
|
||||||
const commands = props?.commands || button.commands;
|
|
||||||
const commandsArray = Array.isArray(commands) ? commands : [commands];
|
|
||||||
const firstCommand = commandsArray[0];
|
|
||||||
|
|
||||||
if (firstCommand?.commandOptions) {
|
|
||||||
return firstCommand.commandOptions.toolName ?? props?.id ?? button.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// use id as a fallback for toolName
|
|
||||||
return props?.id ?? button.id;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -532,6 +532,11 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
|||||||
cameraProps: unknown
|
cameraProps: unknown
|
||||||
): string {
|
): string {
|
||||||
const viewportInfo = this.getViewportInfo(activeViewportId);
|
const viewportInfo = this.getViewportInfo(activeViewportId);
|
||||||
|
|
||||||
|
if (viewportInfo.getViewportType() === csEnums.ViewportType.VOLUME_3D) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const { referencedImageId } = cameraProps;
|
const { referencedImageId } = cameraProps;
|
||||||
if (viewportInfo?.contains(displaySetInstanceUID, referencedImageId)) {
|
if (viewportInfo?.contains(displaySetInstanceUID, referencedImageId)) {
|
||||||
return activeViewportId;
|
return activeViewportId;
|
||||||
|
|||||||
@ -1,4 +1,10 @@
|
|||||||
import { Types, Enums } from '@cornerstonejs/core';
|
import {
|
||||||
|
Types,
|
||||||
|
Enums,
|
||||||
|
getEnabledElementByViewportId,
|
||||||
|
VolumeViewport,
|
||||||
|
utilities,
|
||||||
|
} from '@cornerstonejs/core';
|
||||||
import { Types as CoreTypes } from '@ohif/core';
|
import { Types as CoreTypes } from '@ohif/core';
|
||||||
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
|
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
|
||||||
import getCornerstoneBlendMode from '../../utils/getCornerstoneBlendMode';
|
import getCornerstoneBlendMode from '../../utils/getCornerstoneBlendMode';
|
||||||
@ -89,13 +95,30 @@ const DEFAULT_TOOLGROUP_ID = 'default';
|
|||||||
|
|
||||||
// Return true if the data contains the given display set UID OR the imageId
|
// Return true if the data contains the given display set UID OR the imageId
|
||||||
// if it is a composite object.
|
// if it is a composite object.
|
||||||
const dataContains = (data, displaySetUID: string, imageId?: string): boolean => {
|
const dataContains = ({ data, displaySetUID, imageId, viewport }): boolean => {
|
||||||
if (data.displaySetInstanceUID === displaySetUID) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (imageId && data.isCompositeStack && data.imageIds) {
|
if (imageId && data.isCompositeStack && data.imageIds) {
|
||||||
return !!data.imageIds.find(dataId => dataId === imageId);
|
return !!data.imageIds.find(dataId => dataId === imageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (imageId && (data.volumeId || viewport instanceof VolumeViewport)) {
|
||||||
|
const isAcquisition = !!viewport.getCurrentImageId();
|
||||||
|
|
||||||
|
if (!isAcquisition) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageURI = utilities.imageIdToURI(imageId);
|
||||||
|
const hasImageId = viewport.hasImageURI(imageURI);
|
||||||
|
|
||||||
|
if (hasImageId) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.displaySetInstanceUID === displaySetUID) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,10 +145,20 @@ class ViewportInfo {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { viewport } = getEnabledElementByViewportId(this.viewportId) || {};
|
||||||
|
|
||||||
if (this.viewportData.data.length) {
|
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, viewport })
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return dataContains(this.viewportData.data, displaySetUID, imageId);
|
|
||||||
|
return dataContains({
|
||||||
|
data: this.viewportData.data,
|
||||||
|
displaySetUID,
|
||||||
|
imageId,
|
||||||
|
viewport,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public destroy = (): void => {
|
public destroy = (): void => {
|
||||||
|
|||||||
@ -114,6 +114,7 @@ function getMappedAnnotations(annotation, DisplaySetService) {
|
|||||||
unit: modalityUnit,
|
unit: modalityUnit,
|
||||||
mean,
|
mean,
|
||||||
stdDev,
|
stdDev,
|
||||||
|
metadata,
|
||||||
max,
|
max,
|
||||||
area,
|
area,
|
||||||
areaUnit,
|
areaUnit,
|
||||||
|
|||||||
@ -32,8 +32,8 @@
|
|||||||
"start": "yarn run dev"
|
"start": "yarn run dev"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@cornerstonejs/core": "^1.70.13",
|
"@cornerstonejs/core": "^1.70.14",
|
||||||
"@cornerstonejs/tools": "^1.70.13",
|
"@cornerstonejs/tools": "^1.70.14",
|
||||||
"@ohif/core": "3.8.0-beta.92",
|
"@ohif/core": "3.8.0-beta.92",
|
||||||
"@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.92",
|
"@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.92",
|
||||||
"@ohif/ui": "3.8.0-beta.92",
|
"@ohif/ui": "3.8.0-beta.92",
|
||||||
|
|||||||
@ -1,16 +1,5 @@
|
|||||||
import type { Button } from '@ohif/core/types';
|
import type { Button } from '@ohif/core/types';
|
||||||
|
|
||||||
function _createSetToolActiveCommands(toolName) {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
commandName: 'setToolActive',
|
|
||||||
commandOptions: {
|
|
||||||
toolName,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
const toolbarButtons: Button[] = [
|
const toolbarButtons: Button[] = [
|
||||||
{
|
{
|
||||||
id: 'BrushTools',
|
id: 'BrushTools',
|
||||||
@ -26,7 +15,6 @@ const toolbarButtons: Button[] = [
|
|||||||
name: 'evaluate.cornerstone.segmentation',
|
name: 'evaluate.cornerstone.segmentation',
|
||||||
toolNames: ['CircularBrush', 'SphereBrush'],
|
toolNames: ['CircularBrush', 'SphereBrush'],
|
||||||
},
|
},
|
||||||
commands: _createSetToolActiveCommands('CircularBrush'),
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Size (mm)',
|
name: 'Size (mm)',
|
||||||
@ -62,7 +50,6 @@ const toolbarButtons: Button[] = [
|
|||||||
name: 'evaluate.cornerstone.segmentation',
|
name: 'evaluate.cornerstone.segmentation',
|
||||||
toolNames: ['CircularEraser', 'SphereEraser'],
|
toolNames: ['CircularEraser', 'SphereEraser'],
|
||||||
},
|
},
|
||||||
commands: _createSetToolActiveCommands('CircularEraser'),
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Radius (mm)',
|
name: 'Radius (mm)',
|
||||||
@ -98,7 +85,6 @@ const toolbarButtons: Button[] = [
|
|||||||
name: 'evaluate.cornerstone.segmentation',
|
name: 'evaluate.cornerstone.segmentation',
|
||||||
toolNames: ['ThresholdCircularBrush', 'ThresholdSphereBrush'],
|
toolNames: ['ThresholdCircularBrush', 'ThresholdSphereBrush'],
|
||||||
},
|
},
|
||||||
commands: _createSetToolActiveCommands('ThresholdCircularBrush'),
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Radius (mm)',
|
name: 'Radius (mm)',
|
||||||
@ -156,7 +142,6 @@ const toolbarButtons: Button[] = [
|
|||||||
toolNames: ['CircleScissor', 'SphereScissor', 'RectangleScissor'],
|
toolNames: ['CircleScissor', 'SphereScissor', 'RectangleScissor'],
|
||||||
},
|
},
|
||||||
icon: 'icon-tool-shape',
|
icon: 'icon-tool-shape',
|
||||||
commands: _createSetToolActiveCommands('CircleScissor'),
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Shape',
|
name: 'Shape',
|
||||||
|
|||||||
@ -1,16 +1,5 @@
|
|||||||
import type { Button } from '@ohif/core/types';
|
import type { Button } from '@ohif/core/types';
|
||||||
|
|
||||||
function _createSetToolActiveCommands(toolName) {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
commandName: 'setToolActive',
|
|
||||||
commandOptions: {
|
|
||||||
toolName,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
const toolbarButtons: Button[] = [
|
const toolbarButtons: Button[] = [
|
||||||
{
|
{
|
||||||
id: 'BrushTools',
|
id: 'BrushTools',
|
||||||
@ -27,7 +16,6 @@ const toolbarButtons: Button[] = [
|
|||||||
toolNames: ['CircularBrush', 'SphereBrush'],
|
toolNames: ['CircularBrush', 'SphereBrush'],
|
||||||
disabledText: 'Create new segmentation to enable this tool.',
|
disabledText: 'Create new segmentation to enable this tool.',
|
||||||
},
|
},
|
||||||
commands: _createSetToolActiveCommands('CircularBrush'),
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Radius (mm)',
|
name: 'Radius (mm)',
|
||||||
@ -63,7 +51,6 @@ const toolbarButtons: Button[] = [
|
|||||||
name: 'evaluate.cornerstone.segmentation',
|
name: 'evaluate.cornerstone.segmentation',
|
||||||
toolNames: ['CircularEraser', 'SphereEraser'],
|
toolNames: ['CircularEraser', 'SphereEraser'],
|
||||||
},
|
},
|
||||||
commands: _createSetToolActiveCommands('CircularEraser'),
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Radius (mm)',
|
name: 'Radius (mm)',
|
||||||
@ -99,7 +86,6 @@ const toolbarButtons: Button[] = [
|
|||||||
name: 'evaluate.cornerstone.segmentation',
|
name: 'evaluate.cornerstone.segmentation',
|
||||||
toolNames: ['ThresholdCircularBrush', 'ThresholdSphereBrush'],
|
toolNames: ['ThresholdCircularBrush', 'ThresholdSphereBrush'],
|
||||||
},
|
},
|
||||||
commands: _createSetToolActiveCommands('ThresholdCircularBrush'),
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Radius (mm)',
|
name: 'Radius (mm)',
|
||||||
@ -130,22 +116,29 @@ const toolbarButtons: Button[] = [
|
|||||||
{ value: 'ThresholdDynamic', label: 'Dynamic' },
|
{ value: 'ThresholdDynamic', label: 'Dynamic' },
|
||||||
{ value: 'ThresholdRange', label: 'Range' },
|
{ value: 'ThresholdRange', label: 'Range' },
|
||||||
],
|
],
|
||||||
commands: ({ value, commandsManager }) => {
|
commands: ({ value, commandsManager, options }) => {
|
||||||
if (value === 'ThresholdDynamic') {
|
if (value === 'ThresholdDynamic') {
|
||||||
commandsManager.run('setToolActive', {
|
commandsManager.run('setToolActive', {
|
||||||
toolName: 'ThresholdCircularBrushDynamic',
|
toolName: 'ThresholdCircularBrushDynamic',
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
commandsManager.run('setToolActive', {
|
return;
|
||||||
toolName: 'ThresholdCircularBrush',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check the condition of the threshold-range option
|
||||||
|
const thresholdRangeOption = options.find(
|
||||||
|
option => option.id === 'threshold-shape'
|
||||||
|
);
|
||||||
|
|
||||||
|
commandsManager.run('setToolActiveToolbar', {
|
||||||
|
toolName: thresholdRangeOption.value,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Shape',
|
name: 'Shape',
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
id: 'eraser-mode',
|
id: 'threshold-shape',
|
||||||
value: 'ThresholdCircularBrush',
|
value: 'ThresholdCircularBrush',
|
||||||
values: [
|
values: [
|
||||||
{ value: 'ThresholdCircularBrush', label: 'Circle' },
|
{ value: 'ThresholdCircularBrush', label: 'Circle' },
|
||||||
@ -162,7 +155,7 @@ const toolbarButtons: Button[] = [
|
|||||||
min: -1000,
|
min: -1000,
|
||||||
max: 1000,
|
max: 1000,
|
||||||
step: 1,
|
step: 1,
|
||||||
values: [100, 600],
|
value: [100, 600],
|
||||||
condition: ({ options }) =>
|
condition: ({ options }) =>
|
||||||
options.find(option => option.id === 'dynamic-mode').value === 'ThresholdRange',
|
options.find(option => option.id === 'dynamic-mode').value === 'ThresholdRange',
|
||||||
commands: {
|
commands: {
|
||||||
@ -187,7 +180,6 @@ const toolbarButtons: Button[] = [
|
|||||||
toolNames: ['CircleScissor', 'SphereScissor', 'RectangleScissor'],
|
toolNames: ['CircleScissor', 'SphereScissor', 'RectangleScissor'],
|
||||||
},
|
},
|
||||||
icon: 'icon-tool-shape',
|
icon: 'icon-tool-shape',
|
||||||
commands: _createSetToolActiveCommands('CircleScissor'),
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Shape',
|
name: 'Shape',
|
||||||
|
|||||||
@ -8,18 +8,6 @@ const setToolActiveToolbar = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function _createSetToolActiveCommands(toolName) {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
commandName: 'setToolActiveToolbar',
|
|
||||||
commandOptions: {
|
|
||||||
toolName,
|
|
||||||
toolGroupIds: [toolGroupIds.CT, toolGroupIds.PT, toolGroupIds.Fusion],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
const toolbarButtons = [
|
const toolbarButtons = [
|
||||||
{
|
{
|
||||||
id: 'MeasurementTools',
|
id: 'MeasurementTools',
|
||||||
@ -144,7 +132,6 @@ const toolbarButtons = [
|
|||||||
toolNames: ['CircularBrush', 'SphereBrush'],
|
toolNames: ['CircularBrush', 'SphereBrush'],
|
||||||
disabledText: 'Create new segmentation to enable this tool.',
|
disabledText: 'Create new segmentation to enable this tool.',
|
||||||
},
|
},
|
||||||
commands: _createSetToolActiveCommands('CircularBrush'),
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Radius (mm)',
|
name: 'Radius (mm)',
|
||||||
@ -180,7 +167,6 @@ const toolbarButtons = [
|
|||||||
name: 'evaluate.cornerstone.segmentation',
|
name: 'evaluate.cornerstone.segmentation',
|
||||||
toolNames: ['CircularEraser', 'SphereEraser'],
|
toolNames: ['CircularEraser', 'SphereEraser'],
|
||||||
},
|
},
|
||||||
commands: _createSetToolActiveCommands('CircularEraser'),
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Radius (mm)',
|
name: 'Radius (mm)',
|
||||||
@ -216,7 +202,6 @@ const toolbarButtons = [
|
|||||||
name: 'evaluate.cornerstone.segmentation',
|
name: 'evaluate.cornerstone.segmentation',
|
||||||
toolNames: ['ThresholdCircularBrush', 'ThresholdSphereBrush'],
|
toolNames: ['ThresholdCircularBrush', 'ThresholdSphereBrush'],
|
||||||
},
|
},
|
||||||
commands: _createSetToolActiveCommands('ThresholdCircularBrush'),
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Radius (mm)',
|
name: 'Radius (mm)',
|
||||||
|
|||||||
@ -60,7 +60,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.13",
|
"@babel/runtime": "^7.20.13",
|
||||||
"@kitware/vtk.js": "30.3.3",
|
"@kitware/vtk.js": "30.4.1",
|
||||||
"core-js": "^3.2.1"
|
"core-js": "^3.2.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@ -54,7 +54,7 @@
|
|||||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||||
"@cornerstonejs/codec-openjpeg": "^1.2.2",
|
"@cornerstonejs/codec-openjpeg": "^1.2.2",
|
||||||
"@cornerstonejs/codec-openjph": "^2.4.5",
|
"@cornerstonejs/codec-openjph": "^2.4.5",
|
||||||
"@cornerstonejs/dicom-image-loader": "^1.70.13",
|
"@cornerstonejs/dicom-image-loader": "^1.70.14",
|
||||||
"@emotion/serialize": "^1.1.3",
|
"@emotion/serialize": "^1.1.3",
|
||||||
"@ohif/core": "3.8.0-beta.92",
|
"@ohif/core": "3.8.0-beta.92",
|
||||||
"@ohif/extension-cornerstone": "3.8.0-beta.92",
|
"@ohif/extension-cornerstone": "3.8.0-beta.92",
|
||||||
|
|||||||
@ -125,11 +125,12 @@ function Local({ modePath }: LocalProps) {
|
|||||||
>
|
>
|
||||||
<div className="flex h-screen w-screen items-center justify-center ">
|
<div className="flex h-screen w-screen items-center justify-center ">
|
||||||
<div className="bg-secondary-dark mx-auto space-y-2 rounded-lg py-8 px-8 drop-shadow-md">
|
<div className="bg-secondary-dark mx-auto space-y-2 rounded-lg py-8 px-8 drop-shadow-md">
|
||||||
<img
|
<div className="flex items-center justify-center">
|
||||||
className="mx-auto block h-14"
|
<Icon
|
||||||
src="./ohif-logo.svg"
|
name="logo-dark-background"
|
||||||
alt="OHIF"
|
className="h-28"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
<div className="space-y-2 pt-4 text-center">
|
<div className="space-y-2 pt-4 text-center">
|
||||||
{dropInitiated ? (
|
{dropInitiated ? (
|
||||||
<div className="flex flex-col items-center justify-center pt-48">
|
<div className="flex flex-col items-center justify-center pt-48">
|
||||||
|
|||||||
@ -37,7 +37,7 @@
|
|||||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||||
"@cornerstonejs/codec-openjpeg": "^1.2.2",
|
"@cornerstonejs/codec-openjpeg": "^1.2.2",
|
||||||
"@cornerstonejs/codec-openjph": "^2.4.2",
|
"@cornerstonejs/codec-openjph": "^2.4.2",
|
||||||
"@cornerstonejs/dicom-image-loader": "^1.70.13",
|
"@cornerstonejs/dicom-image-loader": "^1.70.14",
|
||||||
"@ohif/ui": "3.8.0-beta.92",
|
"@ohif/ui": "3.8.0-beta.92",
|
||||||
"cornerstone-math": "0.1.9",
|
"cornerstone-math": "0.1.9",
|
||||||
"dicom-parser": "^1.8.21"
|
"dicom-parser": "^1.8.21"
|
||||||
|
|||||||
@ -204,7 +204,8 @@ export class CommandsManager {
|
|||||||
|
|
||||||
// Execute each command in the array
|
// Execute each command in the array
|
||||||
let result: unknown;
|
let result: unknown;
|
||||||
commands.forEach(({ commandName, commandOptions, context }) => {
|
commands.forEach(command => {
|
||||||
|
const { commandName, commandOptions, context } = command;
|
||||||
if (commandName) {
|
if (commandName) {
|
||||||
result = this.runCommand(
|
result = this.runCommand(
|
||||||
commandName,
|
commandName,
|
||||||
@ -215,7 +216,11 @@ export class CommandsManager {
|
|||||||
context
|
context
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
console.warn('No command name supplied in', toRun);
|
if (typeof command === 'function') {
|
||||||
|
result = command();
|
||||||
|
} else {
|
||||||
|
console.warn('No command name supplied in', toRun);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -156,7 +156,7 @@ export default class ToolbarService extends PubSubService {
|
|||||||
const itemId = interaction.itemId ?? interaction.id;
|
const itemId = interaction.itemId ?? interaction.id;
|
||||||
interaction.itemId = itemId;
|
interaction.itemId = itemId;
|
||||||
|
|
||||||
const commands = Array.isArray(interaction.commands)
|
let commands = Array.isArray(interaction.commands)
|
||||||
? interaction.commands
|
? interaction.commands
|
||||||
: [interaction.commands];
|
: [interaction.commands];
|
||||||
|
|
||||||
@ -170,6 +170,27 @@ export default class ToolbarService extends PubSubService {
|
|||||||
|
|
||||||
const commandOptions = { ...options, ...interaction };
|
const commandOptions = { ...options, ...interaction };
|
||||||
|
|
||||||
|
commands = commands.map(command => {
|
||||||
|
if (typeof command === 'function') {
|
||||||
|
return () => {
|
||||||
|
command({
|
||||||
|
...commandOptions,
|
||||||
|
commandsManager: this._commandsManager,
|
||||||
|
servicesManager: this._servicesManager,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return command;
|
||||||
|
});
|
||||||
|
|
||||||
|
// if still no commands, return
|
||||||
|
commands = commands.filter(Boolean);
|
||||||
|
|
||||||
|
if (!commands.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Loop through commands and run them with the combined options
|
// Loop through commands and run them with the combined options
|
||||||
this._commandsManager.run(commands, commandOptions);
|
this._commandsManager.run(commands, commandOptions);
|
||||||
|
|
||||||
@ -377,6 +398,26 @@ export default class ToolbarService extends PubSubService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the tool name for a given button.
|
||||||
|
* @param button - The button object.
|
||||||
|
* @returns The tool name associated with the button.
|
||||||
|
*/
|
||||||
|
getToolNameForButton(button) {
|
||||||
|
const { props } = button;
|
||||||
|
|
||||||
|
const commands = props?.commands || button.commands;
|
||||||
|
const commandsArray = Array.isArray(commands) ? commands : [commands];
|
||||||
|
const firstCommand = commandsArray[0];
|
||||||
|
|
||||||
|
if (firstCommand?.commandOptions) {
|
||||||
|
return firstCommand.commandOptions.toolName ?? props?.id ?? button.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use id as a fallback for toolName
|
||||||
|
return props?.id ?? button.id;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {*} btn
|
* @param {*} btn
|
||||||
|
|||||||
@ -44,7 +44,7 @@ Key features:
|
|||||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-volume-rendering.webp?raw=true" alt="Volume Rendering" width="350"/> | Volume Rendering | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&hangingprotocolId=mprAnd3DVolumeViewport) |
|
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-volume-rendering.webp?raw=true" alt="Volume Rendering" width="350"/> | Volume Rendering | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&hangingprotocolId=mprAnd3DVolumeViewport) |
|
||||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-pdf.webp?raw=true" alt="PDF" width="350"/> | PDF | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.317377619501274872606137091638706705333) |
|
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-pdf.webp?raw=true" alt="PDF" width="350"/> | PDF | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.317377619501274872606137091638706705333) |
|
||||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-rtstruct.webp?raw=true" alt="RTSTRUCT" width="350"/> | RT STRUCT | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0) |
|
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-rtstruct.webp?raw=true" alt="RTSTRUCT" width="350"/> | RT STRUCT | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0) |
|
||||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-4D.webp?raw=true" alt="4D" width="350"/> | 4D | [Demo](https://viewer.ohif.org/dynamic-volume?StudyInstanceUIDs=2.25.232704420736447710317909004159492840763) |
|
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-4d.webp?raw=true" alt="4D" width="350"/> | 4D | [Demo](https://viewer.ohif.org/dynamic-volume?StudyInstanceUIDs=2.25.232704420736447710317909004159492840763) |
|
||||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-video.webp?raw=true" alt="VIDEO" width="350"/> | Video | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.96975534054447904995905761963464388233) |
|
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/demo-video.webp?raw=true" alt="VIDEO" width="350"/> | Video | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=2.25.96975534054447904995905761963464388233) |
|
||||||
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/microscopy.webp?raw=true" alt="microscopy" width="350"/> | Slide Microscopy | [Demo](https://viewer.ohif.org/microscopy?StudyInstanceUIDs=2.25.141277760791347900862109212450152067508) |
|
| <img src="https://github.com/OHIF/Viewers/blob/master/platform/docs/docs/assets/img/microscopy.webp?raw=true" alt="microscopy" width="350"/> | Slide Microscopy | [Demo](https://viewer.ohif.org/microscopy?StudyInstanceUIDs=2.25.141277760791347900862109212450152067508) |
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 91 KiB |
@ -91,7 +91,7 @@ Let's look at one of the evaluators (for `evaluate.cornerstoneTool`)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const toolName = getToolNameForButton(button);
|
const toolName = toolbarService.getToolNameForButton(button);
|
||||||
|
|
||||||
if (!toolGroup || !toolGroup.hasTool(toolName)) {
|
if (!toolGroup || !toolGroup.hasTool(toolName)) {
|
||||||
return {
|
return {
|
||||||
@ -405,7 +405,12 @@ state will get synchronized with the toolbar service automatically.
|
|||||||
Your toolbox toolbar buttons can have options, this is really useful
|
Your toolbox toolbar buttons can have options, this is really useful
|
||||||
for advanced tools that require to change some parameters. For example, the brush tool that requires the brush size to change or the mode (2D or 3D).
|
for advanced tools that require to change some parameters. For example, the brush tool that requires the brush size to change or the mode (2D or 3D).
|
||||||
|
|
||||||
currently we support three types of options
|
:::note
|
||||||
|
Toolbox with options will run the options commands
|
||||||
|
on the mount of the toolbox component. This is useful for setting the initial state of the toolbox.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Currently we support three types of options.
|
||||||
|
|
||||||
### Radio option
|
### Radio option
|
||||||
|
|
||||||
@ -423,7 +428,6 @@ three different modes
|
|||||||
toolNames: ['CircleScissor', 'SphereScissor', 'RectangleScissor'],
|
toolNames: ['CircleScissor', 'SphereScissor', 'RectangleScissor'],
|
||||||
},
|
},
|
||||||
icon: 'icon-tool-shape',
|
icon: 'icon-tool-shape',
|
||||||
commands: _createSetToolActiveCommands('CircleScissor'),
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Shape',
|
name: 'Shape',
|
||||||
@ -456,7 +460,6 @@ We use this for brush radius change
|
|||||||
toolNames: ['CircularBrush', 'SphereBrush'],
|
toolNames: ['CircularBrush', 'SphereBrush'],
|
||||||
disabledText: 'Create new segmentation to enable this tool.',
|
disabledText: 'Create new segmentation to enable this tool.',
|
||||||
},
|
},
|
||||||
commands: _createSetToolActiveCommands('CircularBrush'),
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Radius (mm)',
|
name: 'Radius (mm)',
|
||||||
|
|||||||
@ -160,3 +160,23 @@ const _initMeasurementService = (MeasurementService, DisplaySetService) => {
|
|||||||
return csToolsVer4MeasurementSource;
|
return csToolsVer4MeasurementSource;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Auto complete
|
||||||
|
Use a customization service to add more customizations for measurement labels. Later, when adding a measurement, the user will be prompted to choose from a list of labels.
|
||||||
|
|
||||||
|
```js
|
||||||
|
customizationService.addModeCustomizations([
|
||||||
|
{
|
||||||
|
id: 'measurementLabels',
|
||||||
|
labelOnMeasure: true,
|
||||||
|
exclusive: true,
|
||||||
|
items: [
|
||||||
|
{ value: 'Head', label: 'Head' },
|
||||||
|
{ value: 'Neck', label: 'Neck' },
|
||||||
|
{ value: 'Knee', label: 'Knee' },
|
||||||
|
{ value: 'Toe', label: 'Toe' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|||||||
20
platform/ui/src/assets/icons/ohif-logo-color-darkbg.svg
Normal file
20
platform/ui/src/assets/icons/ohif-logo-color-darkbg.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 26 KiB |
@ -103,7 +103,7 @@ const renderDoubleRangeSetting = option => {
|
|||||||
key={option.id}
|
key={option.id}
|
||||||
>
|
>
|
||||||
<InputDoubleRange
|
<InputDoubleRange
|
||||||
values={option.values}
|
values={option.value}
|
||||||
onChange={option.commands}
|
onChange={option.commands}
|
||||||
minValue={option.min}
|
minValue={option.min}
|
||||||
maxValue={option.max}
|
maxValue={option.max}
|
||||||
|
|||||||
@ -34,6 +34,7 @@ import link from './../../assets/icons/tool-stack-image-sync.svg';
|
|||||||
import listBullets from './../../assets/icons/list-bullets.svg';
|
import listBullets from './../../assets/icons/list-bullets.svg';
|
||||||
import lock from './../../assets/icons/lock.svg';
|
import lock from './../../assets/icons/lock.svg';
|
||||||
import logoOhifSmall from './../../assets/icons/logo-ohif-small.svg';
|
import logoOhifSmall from './../../assets/icons/logo-ohif-small.svg';
|
||||||
|
import logoDarkBackGround from './../../assets/icons/ohif-logo-color-darkbg.svg';
|
||||||
import magnifier from './../../assets/icons/magnifier.svg';
|
import magnifier from './../../assets/icons/magnifier.svg';
|
||||||
import notificationwarningDiamond from './../../assets/icons/notificationwarning-diamond.svg';
|
import notificationwarningDiamond from './../../assets/icons/notificationwarning-diamond.svg';
|
||||||
import pencil from './../../assets/icons/pencil.svg';
|
import pencil from './../../assets/icons/pencil.svg';
|
||||||
@ -264,6 +265,7 @@ const ICONS = {
|
|||||||
'list-bullets': listBullets,
|
'list-bullets': listBullets,
|
||||||
lock: lock,
|
lock: lock,
|
||||||
'logo-ohif-small': logoOhifSmall,
|
'logo-ohif-small': logoOhifSmall,
|
||||||
|
'logo-dark-background': logoDarkBackGround,
|
||||||
magnifier: magnifier,
|
magnifier: magnifier,
|
||||||
exclamation: exclamation,
|
exclamation: exclamation,
|
||||||
'notificationwarning-diamond': notificationwarningDiamond,
|
'notificationwarning-diamond': notificationwarningDiamond,
|
||||||
|
|||||||
@ -21,6 +21,7 @@ function Toolbox({ servicesManager, buttonSectionId, commandsManager, title, ...
|
|||||||
});
|
});
|
||||||
|
|
||||||
const prevButtonIdsRef = useRef();
|
const prevButtonIdsRef = useRef();
|
||||||
|
const prevToolboxStateRef = useRef();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const currentButtonIdsStr = JSON.stringify(
|
const currentButtonIdsStr = JSON.stringify(
|
||||||
@ -33,11 +34,24 @@ function Toolbox({ servicesManager, buttonSectionId, commandsManager, title, ...
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
if (prevButtonIdsRef.current === currentButtonIdsStr) {
|
const currentToolBoxStateStr = JSON.stringify(
|
||||||
|
Object.keys(toolboxState.toolOptions).map(tool => {
|
||||||
|
const options = toolboxState.toolOptions[tool];
|
||||||
|
if (Array.isArray(options)) {
|
||||||
|
return options?.map(option => `${option.id}-${option.value}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
prevButtonIdsRef.current === currentButtonIdsStr &&
|
||||||
|
prevToolboxStateRef.current === currentToolBoxStateStr
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
prevButtonIdsRef.current = currentButtonIdsStr;
|
prevButtonIdsRef.current = currentButtonIdsStr;
|
||||||
|
prevToolboxStateRef.current = currentToolBoxStateStr;
|
||||||
|
|
||||||
const initializeOptionsWithEnhancements = toolbarButtons.reduce(
|
const initializeOptionsWithEnhancements = toolbarButtons.reduce(
|
||||||
(accumulator, toolbarButton) => {
|
(accumulator, toolbarButton) => {
|
||||||
@ -51,11 +65,15 @@ function Toolbox({ servicesManager, buttonSectionId, commandsManager, title, ...
|
|||||||
return option;
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const value =
|
||||||
|
toolboxState.toolOptions?.[parentId]?.find(prop => prop.id === option.id)?.value ??
|
||||||
|
option.value;
|
||||||
|
|
||||||
|
const updatedOptions = toolboxState.toolOptions?.[parentId];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...option,
|
...option,
|
||||||
value:
|
value,
|
||||||
toolboxState.toolOptions?.[parentId]?.find(prop => prop.id === option.id)?.value ??
|
|
||||||
option.value,
|
|
||||||
commands: value => {
|
commands: value => {
|
||||||
api.handleToolOptionChange(parentId, option.id, value);
|
api.handleToolOptionChange(parentId, option.id, value);
|
||||||
|
|
||||||
@ -72,10 +90,15 @@ function Toolbox({ servicesManager, buttonSectionId, commandsManager, title, ...
|
|||||||
} else if (isObject) {
|
} else if (isObject) {
|
||||||
commandsManager.run({
|
commandsManager.run({
|
||||||
...command,
|
...command,
|
||||||
commandOptions: { ...command.commandOptions, ...option, value },
|
commandOptions: {
|
||||||
|
...command.commandOptions,
|
||||||
|
...option,
|
||||||
|
value,
|
||||||
|
options: updatedOptions,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
} else if (isFunction) {
|
} else if (isFunction) {
|
||||||
command({ value, commandsManager, servicesManager });
|
command({ value, commandsManager, servicesManager, options: updatedOptions });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -101,7 +124,7 @@ function Toolbox({ servicesManager, buttonSectionId, commandsManager, title, ...
|
|||||||
);
|
);
|
||||||
|
|
||||||
api.initializeToolOptions(initializeOptionsWithEnhancements);
|
api.initializeToolOptions(initializeOptionsWithEnhancements);
|
||||||
}, [toolbarButtons, api]);
|
}, [toolbarButtons, api, toolboxState]);
|
||||||
|
|
||||||
const handleToolOptionChange = (toolName, optionName, newValue) => {
|
const handleToolOptionChange = (toolName, optionName, newValue) => {
|
||||||
api.handleToolOptionChange(toolName, optionName, newValue);
|
api.handleToolOptionChange(toolName, optionName, newValue);
|
||||||
|
|||||||
@ -1,9 +1,17 @@
|
|||||||
import React from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import { PanelSection, ToolSettings, Tooltip } from '../../components';
|
import { PanelSection, ToolSettings } from '../../components';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
const ItemsPerRow = 4;
|
const ItemsPerRow = 4;
|
||||||
|
|
||||||
|
function usePrevious(value) {
|
||||||
|
const ref = useRef();
|
||||||
|
useEffect(() => {
|
||||||
|
ref.current = value;
|
||||||
|
});
|
||||||
|
return ref.current;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Just refactoring from the toolbox component to make it more readable
|
* Just refactoring from the toolbox component to make it more readable
|
||||||
*/
|
*/
|
||||||
@ -18,6 +26,27 @@ function ToolboxUI(props) {
|
|||||||
useCollapsedPanel = true,
|
useCollapsedPanel = true,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
const prevToolOptions = usePrevious(activeToolOptions);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!activeToolOptions) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
activeToolOptions.forEach((option, index) => {
|
||||||
|
const prevOption = prevToolOptions ? prevToolOptions[index] : undefined;
|
||||||
|
if (!prevOption || option.value !== prevOption.value) {
|
||||||
|
const isOptionValid = option.condition
|
||||||
|
? option.condition({ options: activeToolOptions })
|
||||||
|
: true;
|
||||||
|
if (isOptionValid) {
|
||||||
|
const { commands } = option;
|
||||||
|
commands(option.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [activeToolOptions]);
|
||||||
|
|
||||||
const render = () => {
|
const render = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -34,7 +63,8 @@ function ToolboxUI(props) {
|
|||||||
const toolClasses = `ml-1 ${isLastRow ? '' : 'mb-2'}`;
|
const toolClasses = `ml-1 ${isLastRow ? '' : 'mb-2'}`;
|
||||||
|
|
||||||
const onInteraction = ({ itemId, id, commands }) => {
|
const onInteraction = ({ itemId, id, commands }) => {
|
||||||
handleToolSelect(itemId || id);
|
const idToUse = itemId || id;
|
||||||
|
handleToolSelect(idToUse);
|
||||||
props.onInteraction({
|
props.onInteraction({
|
||||||
itemId,
|
itemId,
|
||||||
commands,
|
commands,
|
||||||
|
|||||||
@ -78,6 +78,13 @@ const Tooltip = ({
|
|||||||
handleMouseOutDebounced();
|
handleMouseOutDebounced();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
handleMouseOverDebounced.cancel();
|
||||||
|
handleMouseOutDebounced.cancel();
|
||||||
|
};
|
||||||
|
}, [handleMouseOverDebounced, handleMouseOutDebounced]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isOpen && onHide) {
|
if (!isOpen && onHide) {
|
||||||
onHide();
|
onHide();
|
||||||
|
|||||||
58
yarn.lock
58
yarn.lock
@ -1497,13 +1497,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
|
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
|
||||||
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
|
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
|
||||||
|
|
||||||
"@cornerstonejs/adapters@^1.70.13":
|
"@cornerstonejs/adapters@^1.70.14":
|
||||||
version "1.70.13"
|
version "1.70.14"
|
||||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.70.13.tgz#195023f5600272f6ee70090b3c61060d13b9cec7"
|
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.70.14.tgz#1eba07366a66f4d261f3a1e3769260ccf74660af"
|
||||||
integrity sha512-PSitPx/A5aP0VhVTC72trwf3CfVGAXYvcAfAvuk3WzSONhCJ6cg5Xsxpl0NtEt7prsT3u60Bgr94Ea+9VJVdog==
|
integrity sha512-jqMIpvqDH1CPO6rPa7P9CtINOOinwfZpPU6UAuoV8zSJtwOpwViP0Xp9rx9smSmzCc3l3ZZcQ9Wq1DnuzpgPJw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime-corejs2" "^7.17.8"
|
"@babel/runtime-corejs2" "^7.17.8"
|
||||||
"@cornerstonejs/tools" "^1.70.13"
|
"@cornerstonejs/tools" "^1.70.14"
|
||||||
buffer "^6.0.3"
|
buffer "^6.0.3"
|
||||||
dcmjs "^0.29.8"
|
dcmjs "^0.29.8"
|
||||||
gl-matrix "^3.4.3"
|
gl-matrix "^3.4.3"
|
||||||
@ -1550,45 +1550,45 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.5.tgz#8690b61a86fa53ef38a70eee9d665a79229517c0"
|
resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.5.tgz#8690b61a86fa53ef38a70eee9d665a79229517c0"
|
||||||
integrity sha512-MZCUy8VG0VG5Nl1l58+g+kH3LujAzLYTfJqkwpWI2gjSrGXnP6lgwyy4GmPRZWVoS40/B1LDNALK905cNWm+sg==
|
integrity sha512-MZCUy8VG0VG5Nl1l58+g+kH3LujAzLYTfJqkwpWI2gjSrGXnP6lgwyy4GmPRZWVoS40/B1LDNALK905cNWm+sg==
|
||||||
|
|
||||||
"@cornerstonejs/core@^1.70.13":
|
"@cornerstonejs/core@^1.70.14":
|
||||||
version "1.70.13"
|
version "1.70.14"
|
||||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.70.13.tgz#a1976588b93461e2350866ecd761660ee1b74c8d"
|
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.70.14.tgz#f19c9c3da793513b0f6163661f98c633a83ee2b9"
|
||||||
integrity sha512-Bi+ErK6rHNx46CVQiUiw/00ipOWdy7EdyC4U0S30oiLE1Jz1PegIniVDogleXtO1jDkTkNnuWnPCoNhpUgNNuQ==
|
integrity sha512-DrhjlbtGiV9EyHUiGh2RhPzhFQWxZwDCqqkhxBOLl5QiUalByZNyZyN1OHtX0zOyIwVsFw58yvVKYX7s3bpqOw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@kitware/vtk.js" "30.3.3"
|
"@kitware/vtk.js" "30.4.1"
|
||||||
comlink "^4.4.1"
|
comlink "^4.4.1"
|
||||||
detect-gpu "^5.0.22"
|
detect-gpu "^5.0.22"
|
||||||
gl-matrix "^3.4.3"
|
gl-matrix "^3.4.3"
|
||||||
lodash.clonedeep "4.5.0"
|
lodash.clonedeep "4.5.0"
|
||||||
|
|
||||||
"@cornerstonejs/dicom-image-loader@^1.70.13":
|
"@cornerstonejs/dicom-image-loader@^1.70.14":
|
||||||
version "1.70.13"
|
version "1.70.14"
|
||||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.70.13.tgz#cf2aea8b6e538b6f005106ef6401869abde226d2"
|
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.70.14.tgz#3f776bc92b627ec1a80aec0581ee40d06f1ff815"
|
||||||
integrity sha512-PXe9/xmv5vq1raREL9qsD3Ci68pWwCpjVxmyIigpV7lOdtziivvMVNyNSDZCjexBpbsB5a0fKcZG4jl82Jz1HA==
|
integrity sha512-bpYf9s/jhTegxCrrgvvtfJoFDOltkEWAKxqaUjt01g7Z6lnkC6IUaH3XoMZy/0n4un28tTk3xVHF1vAw0upCig==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@cornerstonejs/codec-charls" "^1.2.3"
|
"@cornerstonejs/codec-charls" "^1.2.3"
|
||||||
"@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2"
|
"@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2"
|
||||||
"@cornerstonejs/codec-openjpeg" "^1.2.2"
|
"@cornerstonejs/codec-openjpeg" "^1.2.2"
|
||||||
"@cornerstonejs/codec-openjph" "^2.4.5"
|
"@cornerstonejs/codec-openjph" "^2.4.5"
|
||||||
"@cornerstonejs/core" "^1.70.13"
|
"@cornerstonejs/core" "^1.70.14"
|
||||||
dicom-parser "^1.8.9"
|
dicom-parser "^1.8.9"
|
||||||
pako "^2.0.4"
|
pako "^2.0.4"
|
||||||
uuid "^9.0.0"
|
uuid "^9.0.0"
|
||||||
|
|
||||||
"@cornerstonejs/streaming-image-volume-loader@^1.70.13":
|
"@cornerstonejs/streaming-image-volume-loader@^1.70.14":
|
||||||
version "1.70.13"
|
version "1.70.14"
|
||||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.70.13.tgz#77a3751ddc5ab17cff050007c7e3d7e0b8c58c13"
|
resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.70.14.tgz#e46a4152f6b5ac9a1ce7079d765b8ce9bdcc91ef"
|
||||||
integrity sha512-Pd90y2JFbQ4LriRkkYXXvD3mhIWyiVdGDznhrJN/8ZC+4m5XusOlvOk2Ia/85e+WAgIUlHyDCgOuzewG8of+6w==
|
integrity sha512-yObvU8CB/2F0gLyeRzM5NIxNLQimNHEfJnXuv/EYNATq+wOeKWle3jfUm9xN/ZTiSp1MrBMaG7g26OlyIjEp4Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@cornerstonejs/core" "^1.70.13"
|
"@cornerstonejs/core" "^1.70.14"
|
||||||
comlink "^4.4.1"
|
comlink "^4.4.1"
|
||||||
|
|
||||||
"@cornerstonejs/tools@^1.70.13":
|
"@cornerstonejs/tools@^1.70.14":
|
||||||
version "1.70.13"
|
version "1.70.14"
|
||||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.70.13.tgz#fca6abc331841a2ac1a4403b5522cdcc6cacc708"
|
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.70.14.tgz#7083459c3e206c280cf728d44fe9f4ca09874d2b"
|
||||||
integrity sha512-Eza/4A2p51YPqZbvP6HwZC0yJCkogsda39aB+Eh5VTPQSqHn+VCBmZ9U9Qi9+0cpaye53A5OhjXAOoR6pZlqRQ==
|
integrity sha512-NI4yLC9PNHwa2KO0DqjZET2vZz8VfW095m637gk5E5wojq3dvSJot7w4y+zTCiyaxXjUUoMzc0TJYmmqtdbWPg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@cornerstonejs/core" "^1.70.13"
|
"@cornerstonejs/core" "^1.70.14"
|
||||||
"@icr/polyseg-wasm" "0.4.0"
|
"@icr/polyseg-wasm" "0.4.0"
|
||||||
"@types/offscreencanvas" "2019.7.3"
|
"@types/offscreencanvas" "2019.7.3"
|
||||||
comlink "^4.4.1"
|
comlink "^4.4.1"
|
||||||
@ -2844,10 +2844,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
|
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
|
||||||
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
|
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
|
||||||
|
|
||||||
"@kitware/vtk.js@30.3.3":
|
"@kitware/vtk.js@30.4.1":
|
||||||
version "30.3.3"
|
version "30.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/@kitware/vtk.js/-/vtk.js-30.3.3.tgz#348e17fdc896c912eca7036f607d21ef6128bca1"
|
resolved "https://registry.yarnpkg.com/@kitware/vtk.js/-/vtk.js-30.4.1.tgz#ce8a50012e56341d2d01708a32a2ac3afa675b67"
|
||||||
integrity sha512-es9I5LLlg+TpaIXk5aHSPzyI/YnCI4egHA1cbG98IP7t9W4KODUcJjyrXFAa7aSvfXZ8y2jhD9qrsaEnstEkJA==
|
integrity sha512-jBJFm8AyWpJjNFFBadXyvBwegdD9M6WRdxmIb+x/MVpCyA5lEZSMemhiMn71oKsznaEe5Pjv2VDVJWmwK0vhUg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "7.22.11"
|
"@babel/runtime" "7.22.11"
|
||||||
"@types/webxr" "^0.5.5"
|
"@types/webxr" "^0.5.5"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user