Back to Projects List
- Danny Brown (Radical Imaging)
- James A Petts (Institute for Cancer Research, London)
- Erik Ziegler (Radical Imaging)
- Steve Pieper (Isomics)
- Mete Akdogan (Stanford University, Rubin Lab)
- Zach Saltzaman (Yale School of Medicine)
- Omar Toutounji (Medical Informatics Lab)
The OHIF Viewer is a zero-footprint medical image viewer provided by the Open Health Imaging Foundation (OHIF). It is a configurable and extensible progressive web application with out-of-the-box support for image archives which support DICOMweb. We would like to make the OHIF Viewer easier to extend and customize in order to better support the workflow and feature needs of end users.
Some amount of extensibility is available via OHIF existing extensions. Our objective is specific to our overarching goal of integrating James A Petts existing Segmentation tools and UI, currently maintained here. For example, we would like it to be possible to add the following via plugins:
- Support for custom Commands, Hotkeys, and User Preferences
- Support for custom Side Panels
- Support for custom Toolbar Buttons
- Create and publish
@ohif/extension-segmentation
The OHIF Viewer Platform is currently coupled to it's various components' dependencies and implementations. The goal is to refactor the Viewer to add it's features and functionality via it's own extension/module system. Then, migrate each of the existing components to do the same. Key concepts:
- Create a unit tested
ExtensionManager
responsible for extension and module registration- Enforces consistent module types/interfaces
- At the application level, indicate "active contexts" that modules can scope their behavior/availability to
- Cornerstone Extension's command can only run if "ACTIVE_VIEWPORT::CORNERSTONE" is an active context
- Command definitions are registered to a CommandsManager that other modules have access to
- Modules have the ability to register custom React Components
- Side Panels, Toolbar Buttons, and Hotkeys are primarily driven by configuration; but can specify already registered React Components for advanced customization.
- Utilize Extension/Module system to convert each of Jame's segmentation features to the appropriate module.
- Update implementation as necessary to accommodate his functionality's needs.
- An initial implementation of the Extension Manager
- Basic support for Commands
- Basic support for Toolbar Buttons
- Basic support for Hotkeys
- The
ExtensionManager
was updated to support Panel Extensions - The
ExtensionManager
was updated to support apreRegistration
hook- Also allows for configuration to be passed to extension at Application level
- The
ToolbarDefinition
schema was updated to support nested menu items - Form components were added to
react-viewerbase
to assist Extension Authors - The existing
MeasurementsTable
was converted to aPanelModule
- Authored Segmentation functionality as an
extension
- Add unit tests for, and then simplify how ExtensionManager surfaces its registered modules
- Introduce new UI patterns to improve UX as the number of available tools/panels grows
- Iterate on styles of the Segmentation Extension's custom React Panels
- Add custom SVG Icon support for Toolbar Buttons
- Update
docs.ohif.org
with latest extension information
- Four new toolbar buttons, capable of expanding to show additional options
- Two custom sidepanels that can be toggled using a segmented button group
- Contours and Segments
- SidePanel form and table components that update tool options/configuration and display stored measurements
- Custom tools (Either Cornerstone "Core" tools, or 3rd party drop-ins)
- Addition of alternative display set thumbnail list (See XNAT Nav)
An OHIF extension is a POJO (plain old JavasSript object) that has properties and methods that provide information to OHIF's extension manager.
preRegistration(configuration = {}) {
},
getPanelModule() {
return {
menuOptions: [
{
icon: 'th-list',
label: 'Segments',
target: 'segment-panel'
},
{
icon: 'th',
label: 'Contours',
target: 'contour-panel'
}
],
components: [
{
id: 'segment-panel',
from: 'right',
width: '500px',
component: SegmentationMenu // React Component
},
{
id: 'contour-panel',
from: 'right',
width: '500px',
component: RoiContourMenu // React Component
}
],
defaultContext: ['VIEWER']
};
}
getToolbarModule() {
return {
definitions: [
{
id: 'freehandRoiTools',
label: 'ROI',
icon: 'level',
buttons: [
{
id: 'FreehandRoi',
label: 'Draw',
icon: 'level',
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
commandName: 'setToolActive',
commandOptions: { toolName: TOOL_NAMES.FREEHAND_ROI_3D_TOOL }
},
{
id: 'FreehandRoiSculptor',
label: 'Sculpt',
icon: 'level',
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
commandName: 'setToolActive',
commandOptions: { toolName: TOOL_NAMES.FREEHAND_ROI_3D_SCULPTOR_TOOL }
}
]
},
...
],
defaultContext: 'ACTIVE_VIEWPORT::CORNERSTONE'
};
},
/**
* Registers one or more named commands scoped to a context. Commands are
* the primary means for toolbar actions and actions that can be bound to hotkeys.
*/
getCommandsModule() {
actions: {
nextSegmentForActiveViewport: ({ viewports }) => {
// Command implementation.
},
previousSegmentForActiveViewport: ({ viewports }) => {
// Command implementations.
},
increaseBrushSize: () => {
// Command implementations.
},
decreaseBrushSize: () => {
// Command implementations.
}
}
definitions: {
nextSegmentForActiveViewport: {
commandFn: actions.nextSegmentForActiveViewport,
storeContexts: ['viewports']
},
previousSegmentForActiveViewport: {
commandFn: actions.previousSegmentForActiveViewport,
storeContexts: ['viewports']
},
increaseBrushSize: {
commandFn: actions.increaseBrushSize
},
decreaseBrushSize: {
commandFn: actions.decreaseBrushSize
}
}
defaultContext: 'ACTIVE_VIEWPORT::CORNERSTONE'
};