ohif-viewer/modes/tmtv/src/index.js
Bill Wallace e1d366e1e1
feat: make hanging protocol work on displaySets instead of series (#2837)
* feat(HP): Apply HP to display sets, fix race condition

* fix: displaySetService no event not needed (#2912)

* fix various styles and renamings

* feat: refactored hp service

* fix: use HP service event for viewport grid

* remove unnecessary doc

* fix test

* apply review comment

* fix: segmentation creation

Co-authored-by: Alireza <ar.sedghi@gmail.com>
2022-09-07 11:59:11 -04:00

204 lines
6.1 KiB
JavaScript

import { hotkeys } from '@ohif/core';
import toolbarButtons from './toolbarButtons.js';
import { id } from './id.js';
import initToolGroups, { toolGroupIds } from './initToolGroups.js';
import setCrosshairsConfiguration from './utils/setCrosshairsConfiguration.js';
import setFusionActiveVolume from './utils/setFusionActiveVolume.js';
const ohif = {
layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout',
sopClassHandler: '@ohif/extension-default.sopClassHandlerModule.stack',
hangingProtocols: '@ohif/extension-default.hangingProtocolModule.default',
measurements: '@ohif/extension-default.panelModule.measure',
thumbnailList: '@ohif/extension-default.panelModule.seriesList',
};
const cs3d = {
viewport: '@ohif/extension-cornerstone.viewportModule.cornerstone',
};
const tmtv = {
hangingProtocols: '@ohif/extension-tmtv.hangingProtocolModule.ptCT',
petSUV: '@ohif/extension-tmtv.panelModule.petSUV',
ROIThresholdPanel: '@ohif/extension-tmtv.panelModule.ROIThresholdSeg',
};
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-tmtv': '^3.0.0',
};
let unsubscriptions = [];
function modeFactory({ modeConfiguration }) {
return {
// TODO: We're using this as a route segment
// We should not be.
id,
routeName: 'tmtv',
displayName: 'Total Metabolic Tumor Volume',
/**
* Lifecycle hooks
*/
onModeEnter: ({ servicesManager, extensionManager, commandsManager }) => {
const {
ToolBarService,
ToolGroupService,
HangingProtocolService,
DisplaySetService,
} = servicesManager.services;
const utilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone.utilityModule.tools'
);
const { toolNames, Enums } = utilityModule.exports;
// Init Default and SR ToolGroups
initToolGroups(toolNames, Enums, ToolGroupService, commandsManager);
const setWindowLevelActive = () => {
ToolBarService.recordInteraction({
groupId: 'WindowLevel',
itemId: 'WindowLevel',
interactionType: 'tool',
commands: [
{
commandName: 'setToolActive',
commandOptions: {
toolName: toolNames.WindowLevel,
toolGroupId: toolGroupIds.CT,
},
context: 'CORNERSTONE',
},
{
commandName: 'setToolActive',
commandOptions: {
toolName: toolNames.WindowLevel,
toolGroupId: toolGroupIds.PT,
},
context: 'CORNERSTONE',
},
{
commandName: 'setToolActive',
commandOptions: {
toolName: toolNames.WindowLevel,
toolGroupId: toolGroupIds.Fusion,
},
context: 'CORNERSTONE',
},
],
});
};
// 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
const { unsubscribe } = ToolGroupService.subscribe(
ToolGroupService.EVENTS.VIEWPORT_ADDED,
() => {
// For fusion toolGroup we need to add the volumeIds for the crosshairs
// since in the fusion viewport we don't want both PT and CT to render MIP
// when slabThickness is modified
const {
displaySetMatchDetails,
} = HangingProtocolService.getMatchDetails();
setCrosshairsConfiguration(
displaySetMatchDetails,
toolNames,
ToolGroupService,
DisplaySetService
);
setFusionActiveVolume(
displaySetMatchDetails,
toolNames,
ToolGroupService,
DisplaySetService
);
setWindowLevelActive();
}
);
unsubscriptions.push(unsubscribe);
ToolBarService.init(extensionManager);
ToolBarService.addButtons(toolbarButtons);
ToolBarService.createButtonSection('primary', [
'MeasurementTools',
'Zoom',
'WindowLevel',
'Crosshairs',
'Pan',
'RectangleROIStartEndThreshold',
'fusionPTColormap',
]);
},
onModeExit: ({ servicesManager }) => {
const {
ToolGroupService,
SyncGroupService,
MeasurementService,
ToolBarService,
} = servicesManager.services;
unsubscriptions.forEach(unsubscribe => unsubscribe());
ToolBarService.reset();
MeasurementService.clearMeasurements();
ToolGroupService.destroy();
SyncGroupService.destroy();
},
validationTags: {
study: [],
series: [],
},
isValidMode: ({ modalities }) => {
const modalities_list = modalities.split('\\');
const invalidModalities = ['SM'];
// there should be both CT and PT modalities and the modality should not be SM
return (
modalities_list.includes('CT') &&
modalities_list.includes('PT') &&
!invalidModalities.some(modality => modalities_list.includes(modality))
);
},
routes: [
{
path: 'tmtv',
/*init: ({ servicesManager, extensionManager }) => {
//defaultViewerRouteInit
},*/
layoutTemplate: ({ location, servicesManager }) => {
return {
id: ohif.layout,
props: {
leftPanels: [],
rightPanels: [tmtv.petSUV, tmtv.ROIThresholdPanel],
viewports: [
{
namespace: cs3d.viewport,
displaySetsToDisplay: [ohif.sopClassHandler],
},
],
},
};
},
},
],
extensions: extensionDependencies,
hangingProtocols: [tmtv.hangingProtocols],
sopClassHandlers: [ohif.sopClassHandler],
hotkeys: [...hotkeys.defaults.hotkeyBindings],
};
}
const mode = {
id,
modeFactory,
extensionDependencies,
};
export default mode;