fix(Segmentation): bump packages to fix segmentation rendering (#3138)

* add test mode

* bump packages

* add reference lines

* update yarn lock

* fix netlify build

* fix num workers

* update year in doc
This commit is contained in:
Alireza authored and GitHub committed 2023-02-03 09:33:28 -05:00
1 parent a2bafaf100
commit 123e3a569b
18 files changed
+1172 -43

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
import packageJson from '../package.json';
const id = packageJson.name;
export { id };
+217
View File
@@ -0,0 +1,217 @@
import { hotkeys } from '@ohif/core';
import toolbarButtons from './toolbarButtons.js';
import { id } from './id.js';
import initToolGroups from './initToolGroups.js';
// Allow this mode by excluding non-imaging modalities such as SR, SEG
// Also, SM is not a simple imaging modalities, so exclude it.
const NON_IMAGE_MODALITIES = ['SM', 'ECG', 'SR', 'SEG'];
const ohif = {
layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout',
sopClassHandler: '@ohif/extension-default.sopClassHandlerModule.stack',
thumbnailList: '@ohif/extension-default.panelModule.seriesList',
};
const tracked = {
measurements:
'@ohif/extension-measurement-tracking.panelModule.trackedMeasurements',
thumbnailList: '@ohif/extension-measurement-tracking.panelModule.seriesList',
viewport:
'@ohif/extension-measurement-tracking.viewportModule.cornerstone-tracked',
};
const dicomsr = {
sopClassHandler:
'@ohif/extension-cornerstone-dicom-sr.sopClassHandlerModule.dicom-sr',
viewport: '@ohif/extension-cornerstone-dicom-sr.viewportModule.dicom-sr',
};
const dicomvideo = {
sopClassHandler:
'@ohif/extension-dicom-video.sopClassHandlerModule.dicom-video',
viewport: '@ohif/extension-dicom-video.viewportModule.dicom-video',
};
const dicompdf = {
sopClassHandler: '@ohif/extension-dicom-pdf.sopClassHandlerModule.dicom-pdf',
viewport: '@ohif/extension-dicom-pdf.viewportModule.dicom-pdf',
};
const dicomSeg = {
sopClassHandler:
'@ohif/extension-cornerstone-dicom-seg.sopClassHandlerModule.dicom-seg',
viewport: '@ohif/extension-cornerstone-dicom-seg.viewportModule.dicom-seg',
panel: '@ohif/extension-cornerstone-dicom-seg.panelModule.panelSegmentation',
};
const extensionDependencies = {
// Can derive the versions at least process.env.from npm_package_version
'@ohif/extension-default': '^3.0.0',
'@ohif/extension-cornerstone': '^3.0.0',
'@ohif/extension-measurement-tracking': '^3.0.0',
'@ohif/extension-cornerstone-dicom-sr': '^3.0.0',
'@ohif/extension-cornerstone-dicom-seg': '^3.0.0',
'@ohif/extension-dicom-pdf': '^3.0.1',
'@ohif/extension-dicom-video': '^3.0.1',
};
function modeFactory() {
return {
// TODO: We're using this as a route segment
// We should not be.
id,
routeName: 'basic-test',
displayName: 'Basic Test Mode',
/**
* Lifecycle hooks
*/
onModeEnter: ({ servicesManager, extensionManager, commandsManager }) => {
const {
MeasurementService,
ToolBarService,
ToolGroupService,
} = servicesManager.services;
MeasurementService.clearMeasurements();
// Init Default and SR ToolGroups
initToolGroups(extensionManager, ToolGroupService, commandsManager);
let unsubscribe;
const activateTool = () => {
ToolBarService.recordInteraction({
groupId: 'WindowLevel',
itemId: 'WindowLevel',
interactionType: 'tool',
commands: [
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'WindowLevel',
},
context: 'CORNERSTONE',
},
],
});
// We don't need to reset the active tool whenever a viewport is getting
// added to the toolGroup.
unsubscribe();
};
// Since we only have one viewport for the basic cs3d mode and it has
// only one hanging protocol, we can just use the first viewport
({ unsubscribe } = ToolGroupService.subscribe(
ToolGroupService.EVENTS.VIEWPORT_ADDED,
activateTool
));
ToolBarService.init(extensionManager);
ToolBarService.addButtons(toolbarButtons);
ToolBarService.createButtonSection('primary', [
'MeasurementTools',
'Zoom',
'WindowLevel',
'Pan',
'Capture',
'Layout',
'MPR',
'Crosshairs',
'MoreTools',
]);
},
onModeExit: ({ servicesManager }) => {
const {
ToolGroupService,
SyncGroupService,
ToolBarService,
SegmentationService,
CornerstoneViewportService,
} = servicesManager.services;
ToolBarService.reset();
ToolGroupService.destroy();
SyncGroupService.destroy();
SegmentationService.destroy();
CornerstoneViewportService.destroy();
},
validationTags: {
study: [],
series: [],
},
isValidMode: function({ modalities }) {
const modalities_list = modalities.split('\\');
// Exclude non-image modalities
return !!modalities_list.filter(
modality => NON_IMAGE_MODALITIES.indexOf(modality) === -1
).length;
},
routes: [
{
path: 'basic-test',
/*init: ({ servicesManager, extensionManager }) => {
//defaultViewerRouteInit
},*/
layoutTemplate: () => {
return {
id: ohif.layout,
props: {
leftPanels: [tracked.thumbnailList],
rightPanels: [dicomSeg.panel, tracked.measurements],
// rightPanelDefaultClosed: true, // optional prop to start with collapse panels
viewports: [
{
namespace: tracked.viewport,
displaySetsToDisplay: [ohif.sopClassHandler],
},
{
namespace: dicomsr.viewport,
displaySetsToDisplay: [dicomsr.sopClassHandler],
},
{
namespace: dicomvideo.viewport,
displaySetsToDisplay: [dicomvideo.sopClassHandler],
},
{
namespace: dicompdf.viewport,
displaySetsToDisplay: [dicompdf.sopClassHandler],
},
{
namespace: dicomSeg.viewport,
displaySetsToDisplay: [dicomSeg.sopClassHandler],
},
],
},
};
},
},
],
extensions: extensionDependencies,
// Default protocol gets self-registered by default in the init
hangingProtocol: 'default',
// Order is important in sop class handlers when two handlers both use
// the same sop class under different situations. In that case, the more
// general handler needs to come last. For this case, the dicomvideo must
// come first to remove video transfer syntax before ohif uses images
sopClassHandlers: [
dicomvideo.sopClassHandler,
dicomSeg.sopClassHandler,
ohif.sopClassHandler,
dicompdf.sopClassHandler,
dicomsr.sopClassHandler,
],
hotkeys: [...hotkeys.defaults.hotkeyBindings],
};
}
const mode = {
id,
modeFactory,
extensionDependencies,
};
export default mode;
+225
View File
@@ -0,0 +1,225 @@
function initDefaultToolGroup(
extensionManager,
ToolGroupService,
commandsManager,
toolGroupId
) {
const utilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone.utilityModule.tools'
);
const { toolNames, Enums } = utilityModule.exports;
const tools = {
active: [
{
toolName: toolNames.WindowLevel,
bindings: [{ mouseButton: Enums.MouseBindings.Primary }],
},
{
toolName: toolNames.Pan,
bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }],
},
{
toolName: toolNames.Zoom,
bindings: [{ mouseButton: Enums.MouseBindings.Secondary }],
},
{ toolName: toolNames.StackScrollMouseWheel, bindings: [] },
],
passive: [
{ toolName: toolNames.Length },
{ toolName: toolNames.ArrowAnnotate },
{ toolName: toolNames.Bidirectional },
{ toolName: toolNames.DragProbe },
{ toolName: toolNames.EllipticalROI },
{ toolName: toolNames.RectangleROI },
{ toolName: toolNames.StackScroll },
{ toolName: toolNames.Angle },
{ toolName: toolNames.Magnify },
{ toolName: toolNames.SegmentationDisplay },
],
// enabled
// disabled
disabled: [{ toolName: toolNames.ReferenceLines }],
};
const toolsConfig = {
[toolNames.ArrowAnnotate]: {
getTextCallback: (callback, eventDetails) =>
commandsManager.runCommand('arrowTextCallback', {
callback,
eventDetails,
}),
changeTextCallback: (data, eventDetails, callback) =>
commandsManager.runCommand('arrowTextCallback', {
callback,
data,
eventDetails,
}),
},
};
ToolGroupService.createToolGroupAndAddTools(toolGroupId, tools, toolsConfig);
}
function initSRToolGroup(extensionManager, ToolGroupService, commandsManager) {
const SRUtilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone-dicom-sr.utilityModule.tools'
);
const CS3DUtilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone.utilityModule.tools'
);
const { toolNames: SRToolNames } = SRUtilityModule.exports;
const { toolNames, Enums } = CS3DUtilityModule.exports;
const tools = {
active: [
{
toolName: toolNames.WindowLevel,
bindings: [
{
mouseButton: Enums.MouseBindings.Primary,
},
],
},
{
toolName: toolNames.Pan,
bindings: [
{
mouseButton: Enums.MouseBindings.Auxiliary,
},
],
},
{
toolName: toolNames.Zoom,
bindings: [
{
mouseButton: Enums.MouseBindings.Secondary,
},
],
},
{
toolName: toolNames.StackScrollMouseWheel,
bindings: [],
},
],
passive: [
{ toolName: SRToolNames.SRLength },
{ toolName: SRToolNames.SRArrowAnnotate },
{ toolName: SRToolNames.SRBidirectional },
{ toolName: SRToolNames.SREllipticalROI },
],
enabled: [
{
toolName: SRToolNames.DICOMSRDisplay,
bindings: [],
},
],
// disabled
};
const toolsConfig = {
[toolNames.ArrowAnnotate]: {
getTextCallback: (callback, eventDetails) =>
commandsManager.runCommand('arrowTextCallback', {
callback,
eventDetails,
}),
changeTextCallback: (data, eventDetails, callback) =>
commandsManager.runCommand('arrowTextCallback', {
callback,
data,
eventDetails,
}),
},
};
const toolGroupId = 'SRToolGroup';
ToolGroupService.createToolGroupAndAddTools(toolGroupId, tools, toolsConfig);
}
function initMPRToolGroup(extensionManager, ToolGroupService, commandsManager) {
const utilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone.utilityModule.tools'
);
const { toolNames, Enums } = utilityModule.exports;
const tools = {
active: [
{
toolName: toolNames.WindowLevel,
bindings: [{ mouseButton: Enums.MouseBindings.Primary }],
},
{
toolName: toolNames.Pan,
bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }],
},
{
toolName: toolNames.Zoom,
bindings: [{ mouseButton: Enums.MouseBindings.Secondary }],
},
{ toolName: toolNames.StackScrollMouseWheel, bindings: [] },
],
passive: [
{ toolName: toolNames.Length },
{ toolName: toolNames.ArrowAnnotate },
{ toolName: toolNames.Bidirectional },
{ toolName: toolNames.DragProbe },
{ toolName: toolNames.EllipticalROI },
{ toolName: toolNames.RectangleROI },
{ toolName: toolNames.StackScroll },
{ toolName: toolNames.Angle },
{ toolName: toolNames.SegmentationDisplay },
],
disabled: [
{ toolName: toolNames.Crosshairs },
{ toolName: toolNames.ReferenceLines },
],
// enabled
// disabled
};
const toolsConfig = {
[toolNames.Crosshairs]: {
viewportIndicators: false,
autoPan: {
enabled: false,
panSize: 10,
},
},
[toolNames.ArrowAnnotate]: {
getTextCallback: (callback, eventDetails) =>
commandsManager.runCommand('arrowTextCallback', {
callback,
eventDetails,
}),
changeTextCallback: (data, eventDetails, callback) =>
commandsManager.runCommand('arrowTextCallback', {
callback,
data,
eventDetails,
}),
},
};
ToolGroupService.createToolGroupAndAddTools('mpr', tools, toolsConfig);
}
function initToolGroups(extensionManager, ToolGroupService, commandsManager) {
initDefaultToolGroup(
extensionManager,
ToolGroupService,
commandsManager,
'default'
);
initSRToolGroup(extensionManager, ToolGroupService, commandsManager);
initMPRToolGroup(extensionManager, ToolGroupService, commandsManager);
}
export default initToolGroups;
+544
View File
@@ -0,0 +1,544 @@
// 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 {
// ExpandableToolbarButton,
// ListMenu,
WindowLevelMenuItem,
} from '@ohif/ui';
import { defaults } from '@ohif/core';
const { windowLevelPresets } = defaults;
/**
*
* @param {*} type - 'tool' | 'action' | 'toggle'
* @param {*} id
* @param {*} icon
* @param {*} label
*/
function _createButton(type, id, icon, label, commands, tooltip, uiType) {
return {
id,
icon,
label,
type,
commands,
tooltip,
uiType,
};
}
function _createCommands(commandName, toolName, toolGroupIds) {
return toolGroupIds.map(toolGroupId => ({
/* It's a command that is being run when the button is clicked. */
commandName,
commandOptions: {
toolName,
toolGroupId,
},
context: 'CORNERSTONE',
}));
}
const _createActionButton = _createButton.bind(null, 'action');
const _createToggleButton = _createButton.bind(null, 'toggle');
const _createToolButton = _createButton.bind(null, 'tool');
/**
*
* @param {*} preset - preset number (from above import)
* @param {*} title
* @param {*} subtitle
*/
function _createWwwcPreset(preset, title, subtitle) {
return {
id: preset.toString(),
title,
subtitle,
type: 'action',
commands: [
{
commandName: 'setWindowLevel',
commandOptions: {
...windowLevelPresets[preset],
},
context: 'CORNERSTONE',
},
],
};
}
const toolbarButtons = [
// Measurement
{
id: 'MeasurementTools',
type: 'ohif.splitButton',
props: {
groupId: 'MeasurementTools',
isRadio: true, // ?
// Switch?
primary: _createToolButton(
'Length',
'tool-length',
'Length',
[
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'Length',
},
context: 'CORNERSTONE',
},
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'SRLength',
toolGroupId: 'SRToolGroup',
},
// we can use the setToolActive command for this from Cornerstone commandsModule
context: 'CORNERSTONE',
},
],
'Length'
),
secondary: {
icon: 'chevron-down',
label: '',
isActive: true,
tooltip: 'More Measure Tools',
},
items: [
_createToolButton(
'Length',
'tool-length',
'Length',
[
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'Length',
},
context: 'CORNERSTONE',
},
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'SRLength',
toolGroupId: 'SRToolGroup',
},
// we can use the setToolActive command for this from Cornerstone commandsModule
context: 'CORNERSTONE',
},
],
'Length Tool'
),
_createToolButton(
'Bidirectional',
'tool-bidirectional',
'Bidirectional',
[
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'Bidirectional',
},
context: 'CORNERSTONE',
},
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'SRBidirectional',
toolGroupId: 'SRToolGroup',
},
context: 'CORNERSTONE',
},
],
'Bidirectional Tool'
),
_createToolButton(
'ArrowAnnotate',
'tool-annotate',
'Annotation',
[
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'ArrowAnnotate',
},
context: 'CORNERSTONE',
},
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'SRArrowAnnotate',
toolGroupId: 'SRToolGroup',
},
context: 'CORNERSTONE',
},
],
'Arrow Annotate'
),
_createToolButton(
'EllipticalROI',
'tool-elipse',
'Ellipse',
[
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'EllipticalROI',
},
context: 'CORNERSTONE',
},
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'SREllipticalROI',
toolGroupId: 'SRToolGroup',
},
context: 'CORNERSTONE',
},
],
'Ellipse Tool'
),
],
},
},
// Zoom..
{
id: 'Zoom',
type: 'ohif.radioGroup',
props: {
type: 'tool',
icon: 'tool-zoom',
label: 'Zoom',
commands: [
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'Zoom',
},
context: 'CORNERSTONE',
},
],
},
},
// Window Level + Presets...
{
id: 'WindowLevel',
type: 'ohif.splitButton',
props: {
groupId: 'WindowLevel',
primary: _createToolButton(
'WindowLevel',
'tool-window-level',
'Window Level',
[
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'WindowLevel',
},
context: 'CORNERSTONE',
},
],
'Window Level'
),
secondary: {
icon: 'chevron-down',
label: 'W/L Manual',
isActive: true,
tooltip: 'W/L Presets',
},
isAction: true, // ?
renderer: WindowLevelMenuItem,
items: [
_createWwwcPreset(1, 'Soft tissue', '400 / 40'),
_createWwwcPreset(2, 'Lung', '1500 / -600'),
_createWwwcPreset(3, 'Liver', '150 / 90'),
_createWwwcPreset(4, 'Bone', '2500 / 480'),
_createWwwcPreset(5, 'Brain', '80 / 40'),
],
},
},
// Pan...
{
id: 'Pan',
type: 'ohif.radioGroup',
props: {
type: 'tool',
icon: 'tool-move',
label: 'Pan',
commands: [
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'Pan',
},
context: 'CORNERSTONE',
},
],
},
},
{
id: 'Capture',
type: 'ohif.action',
props: {
icon: 'tool-capture',
label: 'Capture',
type: 'action',
commands: [
{
commandName: 'showDownloadViewportModal',
commandOptions: {},
context: 'CORNERSTONE',
},
],
},
},
{
id: 'Layout',
type: 'ohif.layoutSelector',
props: {
rows: 3,
columns: 3,
},
},
{
id: 'MPR',
type: 'ohif.action',
props: {
type: 'toggle',
icon: 'icon-mpr',
label: 'MPR',
commands: [
{
commandName: 'toggleMPR',
commandOptions: {},
context: 'CORNERSTONE',
},
],
},
},
{
id: 'Crosshairs',
type: 'ohif.radioGroup',
props: {
type: 'tool',
icon: 'tool-crosshair',
label: 'Crosshairs',
commands: [
{
commandName: 'setToolActive',
commandOptions: {
toolGroupId: 'mpr',
toolName: 'Crosshairs',
},
context: 'CORNERSTONE',
},
],
},
},
// More...
{
id: 'MoreTools',
type: 'ohif.splitButton',
props: {
isRadio: true, // ?
groupId: 'MoreTools',
primary: _createActionButton(
'Reset',
'tool-reset',
'Reset View',
[
{
commandName: 'resetViewport',
commandOptions: {},
context: 'CORNERSTONE',
},
],
'Reset'
),
secondary: {
icon: 'chevron-down',
label: '',
isActive: true,
tooltip: 'More Tools',
},
items: [
_createActionButton(
'Reset',
'tool-reset',
'Reset View',
[
{
commandName: 'resetViewport',
commandOptions: {},
context: 'CORNERSTONE',
},
],
'Reset'
),
_createActionButton(
'rotate-right',
'tool-rotate-right',
'Rotate Right',
[
{
commandName: 'rotateViewportCW',
commandOptions: {},
context: 'CORNERSTONE',
},
],
'Rotate +90'
),
_createActionButton(
'flip-horizontal',
'tool-flip-horizontal',
'Flip Horizontally',
[
{
commandName: 'flipViewportHorizontal',
commandOptions: {},
context: 'CORNERSTONE',
},
],
'Flip Horizontal'
),
_createToggleButton('StackImageSync', 'link', 'Stack Image Sync', [
{
commandName: 'toggleStackImageSync',
commandOptions: {},
context: 'CORNERSTONE',
},
]),
_createToggleButton(
'ReferenceLines',
'tool-referenceLines', // change this with the new icon
'Reference Lines',
[
{
commandName: 'toggleReferenceLines',
commandOptions: {},
context: 'CORNERSTONE',
},
]
),
_createToolButton(
'StackScroll',
'tool-stack-scroll',
'Stack Scroll',
[
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'StackScroll',
},
context: 'CORNERSTONE',
},
],
'Stack Scroll'
),
_createActionButton(
'invert',
'tool-invert',
'Invert',
[
{
commandName: 'invertViewport',
commandOptions: {},
context: 'CORNERSTONE',
},
],
'Invert Colors'
),
_createToolButton(
'Probe',
'tool-probe',
'Probe',
[
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'DragProbe',
},
context: 'CORNERSTONE',
},
],
'Probe'
),
_createToggleButton(
'cine',
'tool-cine',
'Cine',
[
{
commandName: 'toggleCine',
context: 'CORNERSTONE',
},
],
'Cine'
),
_createToolButton(
'Angle',
'tool-angle',
'Angle',
[
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'Angle',
},
context: 'CORNERSTONE',
},
],
'Angle'
),
_createToolButton(
'Magnify',
'tool-magnify',
'Magnify',
[
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'Magnify',
},
context: 'CORNERSTONE',
},
],
'Magnify'
),
_createToolButton(
'Rectangle',
'tool-rectangle',
'Rectangle',
[
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'RectangleROI',
},
context: 'CORNERSTONE',
},
],
'Rectangle'
),
_createActionButton(
'TagBrowser',
'list-bullets',
'Dicom Tag Browser',
[
{
commandName: 'openDICOMTagViewer',
commandOptions: {},
context: 'DEFAULT',
},
],
'Dicom Tag Browser'
),
],
},
},
];
export default toolbarButtons;