feat(layout): new layout selector with 3D volume rendering (#3923)

This commit is contained in:
Ibrahim authored and GitHub committed 2024-03-28 10:40:32 -04:00
1 parent 6f610b09e1
commit 617043fe0d
51 files changed
+829 -239

No files matched your search

+1 -1
View File
@@ -148,7 +148,7 @@ const toolbarButtons: Button[] = [
uiType: 'ohif.layoutSelector',
props: {
rows: 3,
columns: 3,
columns: 4,
evaluate: 'evaluate.action',
commands: [
{
@@ -193,10 +193,38 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) {
toolGroupService.createToolGroupAndAddTools('mpr', tools);
}
function initVolume3DToolGroup(extensionManager, toolGroupService) {
const utilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone.utilityModule.tools'
);
const { toolNames, Enums } = utilityModule.exports;
const tools = {
active: [
{
toolName: toolNames.TrackballRotateTool,
bindings: [{ mouseButton: Enums.MouseBindings.Primary }],
},
{
toolName: toolNames.Zoom,
bindings: [{ mouseButton: Enums.MouseBindings.Secondary }],
},
{
toolName: toolNames.Pan,
bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }],
},
],
};
toolGroupService.createToolGroupAndAddTools('volume3d', tools);
}
function initToolGroups(extensionManager, toolGroupService, commandsManager) {
initDefaultToolGroup(extensionManager, toolGroupService, commandsManager, 'default');
initSRToolGroup(extensionManager, toolGroupService, commandsManager);
initMPRToolGroup(extensionManager, toolGroupService, commandsManager);
initVolume3DToolGroup(extensionManager, toolGroupService);
}
export default initToolGroups;
+37 -23
View File
@@ -155,6 +155,41 @@ const toolbarButtons: Button[] = [
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'MPR',
uiType: 'ohif.radioGroup',
props: {
icon: 'icon-mpr',
label: 'MPR',
commands: [
{
commandName: 'toggleHangingProtocol',
commandOptions: {
protocolId: 'mpr',
},
},
],
evaluate: 'evaluate.mpr',
},
},
{
id: 'TrackBallRotate',
type: 'ohif.radioGroup',
props: {
type: 'tool',
icon: 'tool-3d-rotate',
label: '3D Rotate',
commands: [
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'TrackBallRotate',
},
context: 'CORNERSTONE',
},
],
},
},
{
id: 'Capture',
uiType: 'ohif.radioGroup',
@@ -174,30 +209,9 @@ const toolbarButtons: Button[] = [
uiType: 'ohif.layoutSelector',
props: {
rows: 3,
columns: 3,
columns: 4,
evaluate: 'evaluate.action',
commands: [
{
commandName: 'setViewportGridLayout',
},
],
},
},
{
id: 'MPR',
uiType: 'ohif.radioGroup',
props: {
icon: 'icon-mpr',
label: 'MPR',
commands: [
{
commandName: 'toggleHangingProtocol',
commandOptions: {
protocolId: 'mpr',
},
},
],
evaluate: 'evaluate.mpr',
commands: 'setViewportGridLayout',
},
},
{
+2 -2
View File
@@ -83,11 +83,11 @@ function modeFactory({ modeConfiguration }) {
toolbarService.createButtonSection('primary', [
'MeasurementTools',
'Zoom',
'WindowLevel',
'Pan',
'TrackballRotate',
'WindowLevel',
'Capture',
'Layout',
'MPR',
'Crosshairs',
'MoreTools',
]);
+3 -3
View File
@@ -54,7 +54,7 @@ const moreTools = [
label: 'Flip Horizontal',
tooltip: 'Flip Horizontally',
commands: 'flipViewportHorizontal',
evaluate: 'evaluate.viewportProperties.toggle',
evaluate: ['evaluate.viewportProperties.toggle', 'evaluate.not3D'],
}),
createButton({
id: 'ImageSliceSync',
@@ -73,7 +73,7 @@ const moreTools = [
commandOptions: { toggledState: true },
},
},
evaluate: 'evaluate.cornerstone.synchronizer',
evaluate: ['evaluate.cornerstone.synchronizer', 'evaluate.not3D'],
}),
createButton({
id: 'ReferenceLines',
@@ -137,7 +137,7 @@ const moreTools = [
label: 'Cine',
tooltip: 'Cine',
commands: 'toggleCine',
evaluate: 'evaluate.cine',
evaluate: ['evaluate.cine', 'evaluate.not3D'],
}),
createButton({
id: 'Angle',
+14 -23
View File
@@ -1,9 +1,6 @@
// TODO: torn, can either bake this here; or have to create a whole new button type
// Only ways that you can pass in a custom React component for render :l
import {
// ListMenu,
WindowLevelMenuItem,
} from '@ohif/ui';
import { WindowLevelMenuItem } from '@ohif/ui';
import { defaults, ToolbarService } from '@ohif/core';
import type { Button } from '@ohif/core/types';
@@ -36,7 +33,7 @@ function _createWwwcPreset(preset, title, subtitle) {
export const setToolActiveToolbar = {
commandName: 'setToolActiveToolbar',
commandOptions: {
toolGroupIds: ['default', 'mpr', 'SRToolGroup'],
toolGroupIds: ['default', 'mpr', 'SRToolGroup', 'volume3d'],
},
};
@@ -155,6 +152,17 @@ const toolbarButtons: Button[] = [
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'TrackballRotate',
uiType: 'ohif.radioGroup',
props: {
type: 'tool',
icon: 'tool-3d-rotate',
label: '3D Rotate',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'Capture',
uiType: 'ohif.radioGroup',
@@ -174,7 +182,7 @@ const toolbarButtons: Button[] = [
uiType: 'ohif.layoutSelector',
props: {
rows: 3,
columns: 3,
columns: 4,
evaluate: 'evaluate.action',
commands: [
{
@@ -183,23 +191,6 @@ const toolbarButtons: Button[] = [
],
},
},
{
id: 'MPR',
uiType: 'ohif.radioGroup',
props: {
icon: 'icon-mpr',
label: 'MPR',
commands: [
{
commandName: 'toggleHangingProtocol',
commandOptions: {
protocolId: 'mpr',
},
},
],
evaluate: 'evaluate.mpr',
},
},
{
id: 'Crosshairs',
uiType: 'ohif.radioGroup',
+8 -1
View File
@@ -35,7 +35,14 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
"@ohif/core": "3.8.0-beta.64"
"@ohif/core": "3.8.0-beta.64",
"@ohif/extension-cornerstone": "3.8.0-beta.64",
"@ohif/extension-cornerstone-dicom-rt": "3.8.0-beta.64",
"@ohif/extension-cornerstone-dicom-seg": "3.8.0-beta.64",
"@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.64",
"@ohif/extension-default": "3.8.0-beta.64",
"@ohif/extension-dicom-pdf": "3.8.0-beta.64",
"@ohif/extension-dicom-video": "3.8.0-beta.64"
},
"dependencies": {
"@babel/runtime": "^7.20.13",
+13 -5
View File
@@ -4,6 +4,9 @@ import toolbarButtons from './toolbarButtons';
import segmentationButtons from './segmentationButtons';
import initToolGroups from './initToolGroups';
const DEFAULT_TOOL_GROUP_ID = 'default';
const VOLUME3D_TOOL_GROUP_ID = 'volume3d';
const ohif = {
layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout',
sopClassHandler: '@ohif/extension-default.sopClassHandlerModule.stack',
@@ -62,12 +65,13 @@ function modeFactory({ modeConfiguration }) {
toolbarService.addButtons(segmentationButtons);
toolbarService.createButtonSection('primary', [
'WindowLevel',
'Pan',
'Zoom',
'TrackballRotate',
'Capture',
'Layout',
'MPR',
'Crosshairs',
'Zoom',
'MoreTools',
]);
toolbarService.createButtonSection('segmentationToolbox', ['BrushTools', 'Shapes']);
@@ -105,9 +109,13 @@ function modeFactory({ modeConfiguration }) {
// that is not supported by the mode
const modalitiesArray = modalities.split('\\');
return {
valid: modalitiesArray.length === 1 ? !['SM', 'US', 'MG', 'OT', 'DOC', 'CR'].includes(modalitiesArray[0]) : true,
description: 'The mode does not support studies that ONLY include the following modalities: SM, US, MG, OT, DOC, CR',
}
valid:
modalitiesArray.length === 1
? !['SM', 'US', 'MG', 'OT', 'DOC', 'CR'].includes(modalitiesArray[0])
: true,
description:
'The mode does not support studies that ONLY include the following modalities: SM, US, MG, OT, DOC, CR',
};
},
/**
* Mode Routes are used to define the mode's behavior. A list of Mode Route
+29
View File
@@ -81,6 +81,7 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) {
toolName: utilityModule.exports.toolNames.Crosshairs,
configuration: {
viewportIndicators: false,
disableOnPassive: true,
autoPan: {
enabled: false,
panSize: 10,
@@ -92,9 +93,37 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) {
toolGroupService.createToolGroupAndAddTools('mpr', tools);
}
function initVolume3DToolGroup(extensionManager, toolGroupService) {
const utilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone.utilityModule.tools'
);
const { toolNames, Enums } = utilityModule.exports;
const tools = {
active: [
{
toolName: toolNames.TrackballRotateTool,
bindings: [{ mouseButton: Enums.MouseBindings.Primary }],
},
{
toolName: toolNames.Zoom,
bindings: [{ mouseButton: Enums.MouseBindings.Secondary }],
},
{
toolName: toolNames.Pan,
bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }],
},
],
};
toolGroupService.createToolGroupAndAddTools('volume3d', tools);
}
function initToolGroups(extensionManager, toolGroupService, commandsManager) {
initDefaultToolGroup(extensionManager, toolGroupService, commandsManager, 'default');
initMPRToolGroup(extensionManager, toolGroupService, commandsManager);
initVolume3DToolGroup(extensionManager, toolGroupService);
}
export default initToolGroups;
+145 -110
View File
@@ -1,8 +1,16 @@
import { defaults, ToolbarService } from '@ohif/core';
import type { Button } from '@ohif/core/types';
import { defaults, ToolbarService, ViewportGridService } from '@ohif/core';
import { WindowLevelMenuItem } from '@ohif/ui';
const { windowLevelPresets } = defaults;
const { createButton } = ToolbarService;
const ReferenceLinesListeners: RunCommand = [
{
commandName: 'setSourceViewportForReferenceLinesTool',
context: 'CORNERSTONE',
},
];
function _createWwwcPreset(preset, title, subtitle) {
return {
@@ -21,16 +29,12 @@ function _createWwwcPreset(preset, title, subtitle) {
};
}
function _createSetToolActiveCommands(toolName, toolGroupIds = ['default', 'mpr', 'SRToolGroup']) {
return toolGroupIds.map(toolGroupId => ({
commandName: 'setToolActive',
commandOptions: {
toolGroupId,
toolName,
},
context: 'CORNERSTONE',
}));
}
export const setToolActiveToolbar = {
commandName: 'setToolActiveToolbar',
commandOptions: {
toolGroupIds: ['default', 'mpr', 'SRToolGroup'],
},
};
const toolbarButtons: Button[] = [
{
@@ -39,7 +43,7 @@ const toolbarButtons: Button[] = [
props: {
icon: 'tool-zoom',
label: 'Zoom',
commands: _createSetToolActiveCommands('Zoom'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
@@ -48,12 +52,12 @@ const toolbarButtons: Button[] = [
uiType: 'ohif.splitButton',
props: {
groupId: 'WindowLevel',
primary: ToolbarService.createButton({
primary: createButton({
id: 'WindowLevel',
icon: 'tool-window-level',
label: 'Window Level',
tooltip: 'Window Level',
commands: _createSetToolActiveCommands('WindowLevel'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
secondary: {
@@ -76,7 +80,18 @@ const toolbarButtons: Button[] = [
props: {
icon: 'tool-move',
label: 'Pan',
commands: _createSetToolActiveCommands('Pan'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'TrackballRotate',
uiType: 'ohif.radioGroup',
props: {
type: 'tool',
icon: 'tool-3d-rotate',
label: '3D Rotate',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
},
},
@@ -86,12 +101,7 @@ const toolbarButtons: Button[] = [
props: {
icon: 'tool-capture',
label: 'Capture',
commands: [
{
commandName: 'showDownloadViewportModal',
context: 'CORNERSTONE',
},
],
commands: 'showDownloadViewportModal',
evaluate: 'evaluate.action',
},
},
@@ -100,31 +110,9 @@ const toolbarButtons: Button[] = [
uiType: 'ohif.layoutSelector',
props: {
rows: 3,
columns: 3,
columns: 4,
evaluate: 'evaluate.action',
commands: [
{
commandName: 'setViewportGridLayout',
},
],
},
},
{
id: 'MPR',
uiType: 'ohif.radioGroup',
props: {
icon: 'icon-mpr',
label: 'MPR',
commands: [
{
commandName: 'toggleHangingProtocol',
commandOptions: {
protocolId: 'mpr',
},
context: 'DEFAULT',
},
],
evaluate: 'evaluate.mpr',
commands: 'setViewportGridLayout',
},
},
{
@@ -133,7 +121,12 @@ const toolbarButtons: Button[] = [
props: {
icon: 'tool-crosshair',
label: 'Crosshairs',
commands: _createSetToolActiveCommands('Crosshairs', ['mpr']),
commands: {
commandName: 'setToolActiveToolbar',
commandOptions: {
toolGroupIds: ['mpr'],
},
},
evaluate: 'evaluate.cornerstoneTool',
},
},
@@ -143,104 +136,146 @@ const toolbarButtons: Button[] = [
props: {
groupId: 'MoreTools',
evaluate: 'evaluate.group.promoteToPrimaryIfCornerstoneToolNotActiveInTheList',
primary: ToolbarService.createButton({
primary: createButton({
id: 'Reset',
icon: 'tool-reset',
label: 'Reset View',
tooltip: 'Reset',
commands: [
{
commandName: 'resetViewport',
context: 'CORNERSTONE',
},
],
tooltip: 'Reset View',
label: 'Reset',
commands: 'resetViewport',
evaluate: 'evaluate.action',
}),
secondary: {
icon: 'chevron-down',
label: '',
tooltip: 'More Tools',
},
items: [
ToolbarService.createButton({
id: 'RotateRight',
createButton({
id: 'Reset',
icon: 'tool-reset',
label: 'Reset View',
tooltip: 'Reset View',
commands: 'resetViewport',
evaluate: 'evaluate.action',
}),
createButton({
id: 'rotate-right',
icon: 'tool-rotate-right',
label: 'Rotate Right',
tooltip: 'Rotate +90',
commands: [
{
commandName: 'rotateViewportCW',
context: 'CORNERSTONE',
},
],
commands: 'rotateViewportCW',
evaluate: 'evaluate.action',
}),
ToolbarService.createButton({
id: 'FlipHorizontal',
createButton({
id: 'flipHorizontal',
icon: 'tool-flip-horizontal',
label: 'Flip Horizontally',
tooltip: 'Flip Horizontal',
commands: [
{
commandName: 'flipViewportHorizontal',
context: 'CORNERSTONE',
},
],
evaluate: 'evaluate.action',
label: 'Flip Horizontal',
tooltip: 'Flip Horizontally',
commands: 'flipViewportHorizontal',
evaluate: ['evaluate.viewportProperties.toggle', 'evaluate.not3D'],
}),
ToolbarService.createButton({
createButton({
id: 'ReferenceLines',
icon: 'tool-referenceLines',
label: 'Reference Lines',
tooltip: 'Show Reference Lines',
commands: {
commandName: 'setToolEnabled',
commandOptions: {
toolName: 'ReferenceLines',
toggle: true, // Toggle the tool on/off upon click
},
},
listeners: {
[ViewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED]: ReferenceLinesListeners,
[ViewportGridService.EVENTS.VIEWPORTS_READY]: ReferenceLinesListeners,
},
evaluate: 'evaluate.cornerstoneTool.toggle',
}),
createButton({
id: 'ImageOverlay',
icon: 'toggle-dicom-overlay',
label: 'Image Overlay',
tooltip: 'Toggle Image Overlay',
commands: {
commandName: 'setToolEnabled',
commandOptions: {
toolName: 'ImageOverlayViewer',
toggle: true, // Toggle the tool on/off upon click
},
},
evaluate: 'evaluate.cornerstoneTool.toggle',
}),
createButton({
id: 'StackScroll',
icon: 'tool-stack-scroll',
label: 'Stack Scroll',
tooltip: 'Stack Scroll',
commands: _createSetToolActiveCommands('StackScroll'),
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
ToolbarService.createButton({
id: 'Magnify',
icon: 'tool-magnify',
label: 'Magnify',
tooltip: 'Magnify',
commands: _createSetToolActiveCommands('Magnify'),
evaluate: 'evaluate.cornerstoneTool',
}),
ToolbarService.createButton({
id: 'Invert',
createButton({
id: 'invert',
icon: 'tool-invert',
label: 'Invert',
tooltip: 'Invert Colors',
commands: [
{
commandName: 'invertViewport',
context: 'CORNERSTONE',
},
],
evaluate: 'evaluate.action',
commands: 'invertViewport',
evaluate: 'evaluate.viewportProperties.toggle',
}),
ToolbarService.createButton({
createButton({
id: 'Probe',
icon: 'tool-probe',
label: 'Probe',
tooltip: 'Probe',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'Cine',
icon: 'tool-cine',
label: 'Cine',
tooltip: 'Cine',
commands: [
{
commandName: 'toggleCine',
context: 'CORNERSTONE',
},
],
evaluate: 'evaluate.action',
commands: 'toggleCine',
evaluate: ['evaluate.cine', 'evaluate.not3D'],
}),
ToolbarService.createButton({
id: 'DicomTagBrowser',
createButton({
id: 'Angle',
icon: 'tool-angle',
label: 'Angle',
tooltip: 'Angle',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'Magnify',
icon: 'tool-magnify',
label: 'Magnify',
tooltip: 'Magnify',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'RectangleROI',
icon: 'tool-rectangle',
label: 'Rectangle',
tooltip: 'Rectangle',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'CalibrationLine',
icon: 'tool-calibration',
label: 'Calibration',
tooltip: 'Calibration Line',
commands: setToolActiveToolbar,
evaluate: 'evaluate.cornerstoneTool',
}),
createButton({
id: 'TagBrowser',
icon: 'list-bullets',
label: 'Dicom Tag Browser',
tooltip: 'Dicom Tag Browser',
commands: [
{
commandName: 'openDICOMTagViewer',
context: 'DEFAULT',
},
],
evaluate: 'evaluate.action',
commands: 'openDICOMTagViewer',
}),
],
},
-16
View File
@@ -100,22 +100,6 @@ const toolbarButtons = [
evaluate: 'evaluate.cornerstoneTool',
},
},
{
id: 'MPR',
uiType: 'ohif.radioGroup',
props: {
icon: 'icon-mpr',
label: 'MPR',
commands: [
{
commandName: 'toggleHangingProtocol',
commandOptions: { protocolId: 'mpr' },
context: 'DEFAULT',
},
],
evaluate: 'evaluate.mpr',
},
},
// Window Level + Presets
{
id: 'WindowLevel',