diff --git a/plugins/ohifv3/extensions/monai-label/.webpack/webpack.prod.js b/plugins/ohifv3/extensions/monai-label/.webpack/webpack.prod.js
index 2398e36fb..7a7041f03 100644
--- a/plugins/ohifv3/extensions/monai-label/.webpack/webpack.prod.js
+++ b/plugins/ohifv3/extensions/monai-label/.webpack/webpack.prod.js
@@ -1,48 +1,95 @@
-const webpack = require('webpack');
-const { merge } = require('webpack-merge');
const path = require('path');
-const webpackCommon = require('./../../../.webpack/webpack.base.js');
-const pkg = require('./../package.json');
+const pkg = require('../package.json');
-const ROOT_DIR = path.join(__dirname, './..');
-const SRC_DIR = path.join(__dirname, '../src');
-const DIST_DIR = path.join(__dirname, '../dist');
+const outputFile = 'index.umd.js';
+const rootDir = path.resolve(__dirname, '../');
+const outputFolder = path.join(__dirname, `../dist/umd/${pkg.name}/`);
-const ENTRY = {
- app: `${SRC_DIR}/index.tsx`,
-};
-
-module.exports = (env, argv) => {
- const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR, ENTRY });
+// Todo: add ESM build for the extension in addition to umd build
- return merge(commonConfig, {
- stats: {
- colors: true,
- hash: true,
- timings: true,
- assets: true,
- chunks: false,
- chunkModules: false,
- modules: false,
- children: false,
- warnings: true,
- },
- optimization: {
- minimize: true,
- sideEffects: false,
+const config = {
+ mode: 'production',
+ entry: rootDir + '/' + pkg.module,
+ devtool: 'source-map',
+ output: {
+ path: outputFolder,
+ filename: outputFile,
+ library: pkg.name,
+ libraryTarget: 'umd',
+ chunkFilename: '[name].chunk.js',
+ umdNamedDefine: true,
+ globalObject: "typeof self !== 'undefined' ? self : this",
+ },
+ externals: [
+ {
+ react: {
+ root: 'React',
+ commonjs2: 'react',
+ commonjs: 'react',
+ amd: 'react',
+ },
+ '@ohif/core': {
+ commonjs2: '@ohif/core',
+ commonjs: '@ohif/core',
+ amd: '@ohif/core',
+ root: '@ohif/core',
+ },
+ '@ohif/ui': {
+ commonjs2: '@ohif/ui',
+ commonjs: '@ohif/ui',
+ amd: '@ohif/ui',
+ root: '@ohif/ui',
+ },
},
- output: {
- path: ROOT_DIR,
- library: 'ohif-extension-monai-label',
- libraryTarget: 'umd',
- libraryExport: 'default',
- filename: pkg.main,
- },
- externals: [/\b(vtk.js)/, /\b(dcmjs)/, /\b(gl-matrix)/, /^@ohif/, /^@cornerstonejs/],
- plugins: [
- new webpack.optimize.LimitChunkCountPlugin({
- maxChunks: 1,
- }),
+ ],
+ module: {
+ rules: [
+ {
+ test: /\.svg?$/,
+ oneOf: [
+ {
+ use: [
+ {
+ loader: '@svgr/webpack',
+ options: {
+ svgoConfig: {
+ plugins: [
+ {
+ name: 'preset-default',
+ params: {
+ overrides: {
+ removeViewBox: false,
+ },
+ },
+ },
+ ],
+ },
+ prettier: false,
+ svgo: true,
+ titleProp: true,
+ },
+ },
+ ],
+ issuer: {
+ and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
+ },
+ },
+ ],
+ },
+ {
+ test: /(\.jsx|\.js|\.tsx|\.ts)$/,
+ loader: 'babel-loader',
+ exclude: /(node_modules|bower_components)/,
+ resolve: {
+ extensions: ['.js', '.jsx', '.ts', '.tsx'],
+ },
+ },
],
- });
+ },
+ resolve: {
+ modules: [path.resolve('./node_modules'), path.resolve('./src')],
+ extensions: ['.json', '.js', '.jsx', '.tsx', '.ts'],
+ },
};
+
+module.exports = config;
diff --git a/plugins/ohifv3/extensions/monai-label/babel.config.js b/plugins/ohifv3/extensions/monai-label/babel.config.js
index 371f77fcf..4772105a8 100644
--- a/plugins/ohifv3/extensions/monai-label/babel.config.js
+++ b/plugins/ohifv3/extensions/monai-label/babel.config.js
@@ -1,21 +1,5 @@
-// https://babeljs.io/docs/en/options#babelrcroots
-const { extendDefaultPlugins } = require('svgo');
-
module.exports = {
plugins: [
- [
- 'inline-react-svg',
- {
- svgo: {
- plugins: extendDefaultPlugins([
- {
- name: 'removeViewBox',
- active: false,
- },
- ]),
- },
- },
- ],
['@babel/plugin-proposal-class-properties', { loose: true }],
'@babel/plugin-transform-typescript',
['@babel/plugin-proposal-private-property-in-object', { loose: true }],
@@ -59,7 +43,7 @@ module.exports = {
'@babel/preset-react',
'@babel/preset-typescript',
],
- plugins: ['react-hot-loader/babel'],
+ plugins: ['react-refresh/babel'],
ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'],
},
},
diff --git a/plugins/ohifv3/extensions/monai-label/package.json b/plugins/ohifv3/extensions/monai-label/package.json
index 753bfafff..5c5c14d24 100644
--- a/plugins/ohifv3/extensions/monai-label/package.json
+++ b/plugins/ohifv3/extensions/monai-label/package.json
@@ -1,64 +1,77 @@
{
- "name": "@ohif/extension-monai-label",
- "version": "0.0.1",
- "description": "OHIFv3 extension for MONAI Label",
- "author": "OHIF,NVIDIA,KCL",
- "license": "MIT",
- "main": "dist/umd/extension-monai-label/index.umd.js",
- "files": [
- "dist/**",
- "public/**",
- "README.md"
- ],
- "repository": "OHIF/Viewers",
- "keywords": [
- "ohif-extension"
- ],
- "module": "src/index.tsx",
- "publishConfig": {
- "access": "public"
- },
- "engines": {
- "node": ">=14",
- "npm": ">=6",
- "yarn": ">=1.18.0"
- },
- "scripts": {
- "dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo",
- "dev:my-extension": "yarn run dev",
- "build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
- "build:package": "yarn run build",
- "start": "yarn run dev"
- },
- "peerDependencies": {
- "@ohif/core": "^3.7.0-beta.80",
- "@ohif/extension-default": "^3.7.0-beta.80",
- "@ohif/extension-cornerstone": "^3.7.0-beta.80",
- "@ohif/i18n": "^3.7.0-beta.80",
- "prop-types": "^15.6.2",
- "react": "^17.0.2",
- "react-dom": "^17.0.2",
- "react-i18next": "^12.2.2",
- "react-router": "^6.8.1",
- "react-router-dom": "^6.8.1"
- },
- "dependencies": {
- "@babel/runtime": "^7.20.13",
- "md5.js": "^1.3.5",
- "axios": "^0.21.1",
- "arraybuffer-concat": "^0.0.1",
- "ndarray": "^1.0.19",
- "nrrd-js": "^0.2.1",
- "pako": "^2.0.3",
- "react-color": "^2.19.3",
- "bootstrap": "^5.0.2",
- "react-select": "^4.3.1",
- "chroma-js": "^2.1.2",
- "itk": "^14.1.1"
- },
- "devDependencies": {
- "@babel/runtime": "^7.20.13",
- "@cornerstonejs/tools": "^1.16.4",
- "react-color": "^2.19.3"
- }
+ "name": "@ohif/extension-monai-label",
+ "version": "0.0.1",
+ "description": "OHIFv3 extension for MONAI Label",
+ "author": "OHIF,NVIDIA,KCL",
+ "license": "MIT",
+ "main": "dist/umd/extension-monai-label/index.umd.js",
+ "files": [
+ "dist/**",
+ "public/**",
+ "README.md"
+ ],
+ "repository": "OHIF/Viewers",
+ "keywords": [
+ "ohif-extension"
+ ],
+ "module": "src/index.tsx",
+ "publishConfig": {
+ "access": "public"
+ },
+ "engines": {
+ "node": ">=14",
+ "npm": ">=6",
+ "yarn": ">=1.18.0"
+ },
+ "scripts": {
+ "dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo",
+ "dev:my-extension": "yarn run dev",
+ "build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
+ "build:package": "yarn run build",
+ "start": "yarn run dev"
+ },
+ "dependencies": {
+ "@babel/runtime": "^7.20.13",
+ "md5.js": "^1.3.5",
+ "axios": "^0.21.1",
+ "arraybuffer-concat": "^0.0.1",
+ "ndarray": "^1.0.19",
+ "nrrd-js": "^0.2.1",
+ "pako": "^2.0.3",
+ "bootstrap": "^5.0.2",
+ "chroma-js": "^2.1.2",
+ "itk": "^14.1.1",
+ "@ohif/core": "workspace:*",
+ "@ohif/extension-default": "workspace:*",
+ "@ohif/extension-cornerstone": "workspace:*"
+ },
+ "devDependencies": {
+ "@babel/runtime": "^7.20.13",
+ "cross-env": "^5.2.0",
+ "@babel/core": "7.24.7",
+ "@babel/plugin-proposal-class-properties": "^7.16.7",
+ "@babel/plugin-proposal-object-rest-spread": "^7.17.3",
+ "@babel/plugin-proposal-private-methods": "^7.18.6",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-transform-arrow-functions": "^7.16.7",
+ "@babel/plugin-transform-regenerator": "^7.16.7",
+ "@babel/plugin-transform-runtime": "7.24.7",
+ "@babel/plugin-transform-typescript": "^7.13.0",
+ "@babel/preset-env": "7.24.7",
+ "@babel/preset-react": "^7.16.7",
+ "@babel/preset-typescript": "^7.13.0",
+ "@babel/plugin-proposal-private-property-in-object": "7.21.11",
+ "babel-eslint": "9.x",
+ "babel-loader": "^8.2.4",
+ "@svgr/webpack": "^8.1.0",
+ "babel-plugin-module-resolver": "^5.0.0",
+ "clean-webpack-plugin": "^4.0.0",
+ "copy-webpack-plugin": "^10.2.0",
+ "dotenv": "^14.1.0",
+ "eslint": "^8.39.0",
+ "eslint-loader": "^2.0.0",
+ "webpack": "5.89.0",
+ "webpack-merge": "^5.7.3",
+ "webpack-cli": "^5.0.2"
+ }
}
diff --git a/plugins/ohifv3/extensions/monai-label/src/components/MonaiLabelPanel.css b/plugins/ohifv3/extensions/monai-label/src/components/MonaiLabelPanel.css
index 6c069c0ed..445c62bf1 100644
--- a/plugins/ohifv3/extensions/monai-label/src/components/MonaiLabelPanel.css
+++ b/plugins/ohifv3/extensions/monai-label/src/components/MonaiLabelPanel.css
@@ -1,4 +1,3 @@
-@import url("w3.css");
.monaiLabelPanel {
background-color: #789;
diff --git a/plugins/ohifv3/extensions/monai-label/src/components/MonaiLabelPanel.tsx b/plugins/ohifv3/extensions/monai-label/src/components/MonaiLabelPanel.tsx
index f62e3f5d6..72f10c42f 100644
--- a/plugins/ohifv3/extensions/monai-label/src/components/MonaiLabelPanel.tsx
+++ b/plugins/ohifv3/extensions/monai-label/src/components/MonaiLabelPanel.tsx
@@ -2,6 +2,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { cache, triggerEvent, eventTarget } from '@cornerstonejs/core';
import { Enums } from '@cornerstonejs/tools';
+import { Toolbox } from '@ohif/ui-next';
import './MonaiLabelPanel.css';
import SettingsTable from './SettingsTable';
import AutoSegmentation from './actions/AutoSegmentation';
@@ -10,8 +11,7 @@ import OptionTable from './actions/OptionTable';
import ActiveLearning from './actions/ActiveLearning';
import MonaiLabelClient from '../services/MonaiLabelClient';
import SegmentationReader from '../utils/SegmentationReader';
-import MonaiSegmentation from './MonaiSegmentation';
-import SegmentationToolbox from './SegmentationToolbox';
+import { PanelSegmentation } from '@ohif/extension-cornerstone';
export default class MonaiLabelPanel extends Component {
static propTypes = {
@@ -55,25 +55,32 @@ export default class MonaiLabelPanel extends Component {
segmentations: [],
};
- // Todo: fix this hack
- setTimeout(() => {
- const { viewports, activeViewportId } = viewportGridService.getState();
- const viewport = viewports.get(activeViewportId);
- const displaySet = displaySetService.getDisplaySetByUID(
- viewport.displaySetInstanceUIDs[0]
- );
-
- this.SeriesInstanceUID = displaySet.SeriesInstanceUID;
- this.StudyInstanceUID = displaySet.StudyInstanceUID;
- this.FrameOfReferenceUID = displaySet.instances[0].FrameOfReferenceUID;
- this.displaySetInstanceUID = displaySet.displaySetInstanceUID;
- }, 1000);
+ viewportGridService.subscribe(
+ viewportGridService.EVENTS.GRID_SIZE_CHANGED,
+ () => {
+ const { viewports, activeViewportId } = viewportGridService.getState();
+ const viewport = viewports.get(activeViewportId);
+
+ if (!viewport) {
+ return;
+ }
+
+ const displaySet = displaySetService.getDisplaySetByUID(
+ viewport.displaySetInstanceUIDs[0]
+ );
+
+ this.SeriesInstanceUID = displaySet.SeriesInstanceUID;
+ this.StudyInstanceUID = displaySet.StudyInstanceUID;
+ this.FrameOfReferenceUID = displaySet.instances[0].FrameOfReferenceUID;
+ this.displaySetInstanceUID = displaySet.displaySetInstanceUID;
+ }
+ );
}
async componentDidMount() {
const { segmentationService } = this.props.servicesManager.services;
const added = segmentationService.EVENTS.SEGMENTATION_ADDED;
- const updated = segmentationService.EVENTS.SEGMENTATION_UPDATED;
+ const updated = segmentationService.EVENTS.SEGMENTATION_MODIFIED;
const removed = segmentationService.EVENTS.SEGMENTATION_REMOVED;
const subscriptions = [];
@@ -121,23 +128,30 @@ export default class MonaiLabelPanel extends Component {
const response = await this.client().info();
// remove the background
- const labels = response.data.labels.splice(1)
+ const labels = response.data.labels.splice(1);
const segmentations = [
{
- id: '1',
- label: 'Segmentations',
- segments: labels.map((label, index) => ({
- segmentIndex: index + 1,
- label
- })),
- isActive: true,
- activeSegmentIndex: 1,
+ segmentationId: '1',
+ representation: {
+ type: Enums.SegmentationRepresentations.Labelmap,
+ },
+ config: {
+ label: 'Segmentations',
+ segments: labels.reduce((acc, label, index) => {
+ acc[index + 1] = {
+ label,
+ active: index === 0, // First segment is active
+ locked: false,
+ };
+ return acc;
+ }, {}),
+ },
},
];
this.props.commandsManager.runCommand('loadSegmentationsForViewport', {
- segmentations
+ segmentations,
});
if (response.status !== 200) {
@@ -186,6 +200,7 @@ export default class MonaiLabelPanel extends Component {
};
_update = async (response, labelNames) => {
+ const { segmentationService } = this.props.servicesManager.services;
// Process the obtained binary file from the MONAI Label server
/* const onInfoLabelNames = this.state.info.labels */
const onInfoLabelNames = labelNames;
@@ -193,11 +208,10 @@ export default class MonaiLabelPanel extends Component {
console.info('These are the predicted labels');
console.info(onInfoLabelNames);
- if (onInfoLabelNames.hasOwnProperty('background')){
-delete onInfoLabelNames.background;
+ if (onInfoLabelNames.hasOwnProperty('background')) {
+ delete onInfoLabelNames.background;
}
-
const ret = SegmentationReader.parseNrrdData(response.data);
if (!ret) {
@@ -215,36 +229,40 @@ delete onInfoLabelNames.background;
centroidsIJK.set(segmentIndex, { image: image, world: [] });
}
- const segmentations = [
+
+ const segmentationsNew = [
{
- id: '1',
- label: 'Segmentations',
- segments: Object.keys(onInfoLabelNames).map((key) => ({
- segmentIndex: onInfoLabelNames[key],
- label: key,
- })),
- isActive: true,
- activeSegmentIndex: 1,
- scalarData: data,
- FrameOfReferenceUID: this.FrameOfReferenceUID,
+ segmentationId: '1',
+ representation: {
+ type: Enums.SegmentationRepresentations.Labelmap,
+ },
+ config: {
+ FrameOfReferenceUID: this.FrameOfReferenceUID,
+ label: 'Segmentations',
+ segments: Object.keys(onInfoLabelNames).reduce((acc, key) => {
+ const segmentIndex = onInfoLabelNames[key];
+ acc[segmentIndex] = {
+ label: key,
+ active: segmentIndex === 1, // First segment is active
+ locked: false,
+ };
+ return acc;
+ }, {}),
+ },
centroidsIJK: centroidsIJK,
},
];
+ const volume = segmentationService.getLabelmapVolume('1');
// Todo: rename volumeId
- const volumeLoadObject = cache.getVolume('1');
- if (volumeLoadObject) {
- const { scalarData } = volumeLoadObject;
- scalarData.set(data);
+ if (volume) {
+ const { voxelManager } = volume;
+ voxelManager?.setCompleteScalarDataArray(data);
triggerEvent(eventTarget, Enums.Events.SEGMENTATION_DATA_MODIFIED, {
segmentationId: '1',
});
console.debug("updated the segmentation's scalar data");
- } else {
- this.props.commandsManager.runCommand('hydrateSegmentationsForViewport', {
- segmentations,
- });
- }
+ }
};
_debug = async () => {
@@ -387,16 +405,22 @@ delete onInfoLabelNames.background;
/>
- {this.state.segmentations?.map((segmentation) => (
- <>
-
-
- >
- ))}
+
);
}
diff --git a/plugins/ohifv3/extensions/monai-label/src/components/MonaiSegmentation.tsx b/plugins/ohifv3/extensions/monai-label/src/components/MonaiSegmentation.tsx
deleted file mode 100644
index f112a84c8..000000000
--- a/plugins/ohifv3/extensions/monai-label/src/components/MonaiSegmentation.tsx
+++ /dev/null
@@ -1,319 +0,0 @@
-import { createReportAsync } from '@ohif/extension-default';
-import React, { useEffect, useState, useCallback } from 'react';
-import PropTypes from 'prop-types';
-import { SegmentationGroupTable } from '@ohif/ui';
-
-import callInputDialog from './callInputDialog';
-import callColorPickerDialog from './colorPickerDialog';
-import { useTranslation } from 'react-i18next';
-
-export default function MonaiSegmentation({
- servicesManager,
- commandsManager,
- extensionManager,
- configuration,
-}) {
- const { segmentationService, uiDialogService } = servicesManager.services;
-
- const { t } = useTranslation('PanelSegmentation');
-
- const [selectedSegmentationId, setSelectedSegmentationId] = useState(null);
- const [segmentationConfiguration, setSegmentationConfiguration] = useState(
- segmentationService.getConfiguration()
- );
-
- const [segmentations, setSegmentations] = useState(() =>
- segmentationService.getSegmentations()
- );
-
- useEffect(() => {
- // ~~ Subscription
- const added = segmentationService.EVENTS.SEGMENTATION_ADDED;
- const updated = segmentationService.EVENTS.SEGMENTATION_UPDATED;
- const removed = segmentationService.EVENTS.SEGMENTATION_REMOVED;
- const subscriptions = [];
-
- [added, updated, removed].forEach((evt) => {
- const { unsubscribe } = segmentationService.subscribe(evt, () => {
- const segmentations = segmentationService.getSegmentations();
- setSegmentations(segmentations);
- setSegmentationConfiguration(segmentationService.getConfiguration());
- });
- subscriptions.push(unsubscribe);
- });
-
- return () => {
- subscriptions.forEach((unsub) => {
- unsub();
- });
- };
- }, []);
-
- const getToolGroupIds = (segmentationId) => {
- const toolGroupIds =
- segmentationService.getToolGroupIdsWithSegmentation(segmentationId);
-
- return toolGroupIds;
- };
-
- const onSegmentationAdd = async () => {
- commandsManager.runCommand('addSegmentationForActiveViewport');
- };
-
- const onSegmentationClick = (segmentationId: string) => {
- segmentationService.setActiveSegmentationForToolGroup(segmentationId);
- };
-
- const onSegmentationDelete = (segmentationId: string) => {
- segmentationService.remove(segmentationId);
- };
-
- const onSegmentAdd = (segmentationId) => {
- segmentationService.addSegment(segmentationId);
- };
-
- const onSegmentClick = (segmentationId, segmentIndex) => {
- segmentationService.setActiveSegment(segmentationId, segmentIndex);
-
- const toolGroupIds = getToolGroupIds(segmentationId);
-
- toolGroupIds.forEach((toolGroupId) => {
- // const toolGroupId =
- segmentationService.setActiveSegmentationForToolGroup(
- segmentationId,
- toolGroupId
- );
- segmentationService.jumpToSegmentCenter(
- segmentationId,
- segmentIndex,
- toolGroupId
- );
- });
- };
-
- const onSegmentEdit = (segmentationId, segmentIndex) => {
- const segmentation = segmentationService.getSegmentation(segmentationId);
-
- const segment = segmentation.segments[segmentIndex];
- const { label } = segment;
-
- callInputDialog(uiDialogService, label, (label, actionId) => {
- if (label === '') {
- return;
- }
-
- segmentationService.setSegmentLabel(segmentationId, segmentIndex, label);
- });
- };
-
- const onSegmentationEdit = (segmentationId) => {
- const segmentation = segmentationService.getSegmentation(segmentationId);
- const { label } = segmentation;
-
- callInputDialog(uiDialogService, label, (label, actionId) => {
- if (label === '') {
- return;
- }
-
- segmentationService.addOrUpdateSegmentation(
- {
- id: segmentationId,
- label,
- },
- false, // suppress event
- true // notYetUpdatedAtSource
- );
- });
- };
-
- const onSegmentColorClick = (segmentationId, segmentIndex) => {
- const segmentation = segmentationService.getSegmentation(segmentationId);
-
- const segment = segmentation.segments[segmentIndex];
- const { color, opacity } = segment;
-
- const rgbaColor = {
- r: color[0],
- g: color[1],
- b: color[2],
- a: opacity / 255.0,
- };
-
- callColorPickerDialog(
- uiDialogService,
- rgbaColor,
- (newRgbaColor, actionId) => {
- if (actionId === 'cancel') {
- return;
- }
-
- segmentationService.setSegmentRGBAColor(segmentationId, segmentIndex, [
- newRgbaColor.r,
- newRgbaColor.g,
- newRgbaColor.b,
- newRgbaColor.a * 255.0,
- ]);
- }
- );
- };
-
- const onSegmentDelete = (segmentationId, segmentIndex) => {
- segmentationService.removeSegment(segmentationId, segmentIndex);
- };
-
- const onToggleSegmentVisibility = (segmentationId, segmentIndex) => {
- const segmentation = segmentationService.getSegmentation(segmentationId);
- const segmentInfo = segmentation.segments[segmentIndex];
- const isVisible = !segmentInfo.isVisible;
- const toolGroupIds = getToolGroupIds(segmentationId);
-
- // Todo: right now we apply the visibility to all tool groups
- toolGroupIds.forEach((toolGroupId) => {
- segmentationService.setSegmentVisibility(
- segmentationId,
- segmentIndex,
- isVisible,
- toolGroupId
- );
- });
- };
-
- const onToggleSegmentLock = (segmentationId, segmentIndex) => {
- segmentationService.toggleSegmentLocked(segmentationId, segmentIndex);
- };
-
- const onToggleSegmentationVisibility = (segmentationId) => {
- segmentationService.toggleSegmentationVisibility(segmentationId);
- };
-
- const _setSegmentationConfiguration = useCallback(
- (segmentationId, key, value) => {
- segmentationService.setConfiguration({
- segmentationId,
- [key]: value,
- });
- },
- [segmentationService]
- );
-
- const onSegmentationDownload = (segmentationId) => {
- commandsManager.runCommand('downloadSegmentation', {
- segmentationId,
- });
- };
-
- const onSegmentationDownloadRTSS = (segmentationId) => {};
-
- const storeSegmentation = (segmentationId) => {
- const datasources = extensionManager.getActiveDataSource();
-
- const getReport = async () => {
- return await commandsManager.runCommand('storeSegmentation', {
- segmentationId,
- dataSource: datasources[0],
- });
- };
-
- createReportAsync({
- servicesManager,
- getReport,
- reportType: 'Segmentation',
- });
- };
-
- return (
- <>
-
-
- _setSegmentationConfiguration(
- selectedSegmentationId,
- 'renderOutline',
- value
- )
- }
- setOutlineOpacityActive={(value) =>
- _setSegmentationConfiguration(
- selectedSegmentationId,
- 'outlineOpacity',
- value
- )
- }
- setRenderFill={(value) =>
- _setSegmentationConfiguration(
- selectedSegmentationId,
- 'renderFill',
- value
- )
- }
- setRenderInactiveSegmentations={(value) =>
- _setSegmentationConfiguration(
- selectedSegmentationId,
- 'renderInactiveSegmentations',
- value
- )
- }
- setOutlineWidthActive={(value) =>
- _setSegmentationConfiguration(
- selectedSegmentationId,
- 'outlineWidthActive',
- value
- )
- }
- setFillAlpha={(value) =>
- _setSegmentationConfiguration(
- selectedSegmentationId,
- 'fillAlpha',
- value
- )
- }
- setFillAlphaInactive={(value) =>
- _setSegmentationConfiguration(
- selectedSegmentationId,
- 'fillAlphaInactive',
- value
- )
- }
- />
-
- >
- );
-}
-
-MonaiSegmentation.propTypes = {
- commandsManager: PropTypes.shape({
- runCommand: PropTypes.func.isRequired,
- }),
- servicesManager: PropTypes.shape({
- services: PropTypes.shape({
- segmentationService: PropTypes.shape({
- getSegmentation: PropTypes.func.isRequired,
- getSegmentations: PropTypes.func.isRequired,
- toggleSegmentationVisibility: PropTypes.func.isRequired,
- subscribe: PropTypes.func.isRequired,
- EVENTS: PropTypes.object.isRequired,
- }).isRequired,
- }).isRequired,
- }).isRequired,
-};
diff --git a/plugins/ohifv3/extensions/monai-label/src/components/SegmentationToolbox.tsx b/plugins/ohifv3/extensions/monai-label/src/components/SegmentationToolbox.tsx
deleted file mode 100644
index 4577a56b7..000000000
--- a/plugins/ohifv3/extensions/monai-label/src/components/SegmentationToolbox.tsx
+++ /dev/null
@@ -1,368 +0,0 @@
-import React, { useCallback, useEffect, useState, useReducer } from 'react';
-import { AdvancedToolbox, InputDoubleRange, useViewportGrid } from '@ohif/ui';
-import { Types } from '@ohif/extension-cornerstone';
-import { utilities } from '@cornerstonejs/tools';
-
-const { segmentation: segmentationUtils } = utilities;
-
-const ACTIONS = {
- SET_BRUSH_SIZE: 'SET_BRUSH_SIZE',
- SET_TOOL_CONFIG: 'SET_TOOL_CONFIG',
- SET_ACTIVE_TOOL: 'SET_ACTIVE_TOOL',
-};
-
-const initialState = {
- Brush: {
- brushSize: 15,
- mode: 'CircularBrush', // Can be 'CircularBrush' or 'SphereBrush'
- },
- Eraser: {
- brushSize: 15,
- mode: 'CircularEraser', // Can be 'CircularEraser' or 'SphereEraser'
- },
- Scissors: {
- brushSize: 15,
- mode: 'CircleScissor', // E.g., 'CircleScissor', 'RectangleScissor', or 'SphereScissor'
- },
- ThresholdBrush: {
- brushSize: 15,
- thresholdRange: [-500, 500],
- },
- activeTool: null,
-};
-
-function toolboxReducer(state, action) {
- switch (action.type) {
- case ACTIONS.SET_TOOL_CONFIG:
- const { tool, config } = action.payload;
- return {
- ...state,
- [tool]: {
- ...state[tool],
- ...config,
- },
- };
- case ACTIONS.SET_ACTIVE_TOOL:
- return { ...state, activeTool: action.payload };
- default:
- return state;
- }
-}
-
-function SegmentationToolbox({ servicesManager, extensionManager }) {
- const { toolbarService, segmentationService, toolGroupService } =
- servicesManager.services as Types.CornerstoneServices;
-
- const [viewportGrid] = useViewportGrid();
- const { viewports, activeViewportId } = viewportGrid;
-
- const [toolsEnabled, setToolsEnabled] = useState(false);
- const [state, dispatch] = useReducer(toolboxReducer, initialState);
-
- const updateActiveTool = useCallback(() => {
- if (!viewports?.size || activeViewportId === undefined) {
- return;
- }
-
- const viewport = viewports.get(activeViewportId);
-
- dispatch({
- type: ACTIONS.SET_ACTIVE_TOOL,
- payload: toolGroupService.getActiveToolForViewport(viewport.viewportId),
- });
- }, [activeViewportId, viewports, toolGroupService, dispatch]);
-
- /**
- * sets the tools enabled IF there are segmentations
- */
- useEffect(() => {
- const events = [
- segmentationService.EVENTS.SEGMENTATION_ADDED,
- segmentationService.EVENTS.SEGMENTATION_UPDATED,
- ];
-
- const unsubscriptions = [];
-
- events.forEach(event => {
- const { unsubscribe } = segmentationService.subscribe(event, () => {
- const segmentations = segmentationService.getSegmentations();
-
- const activeSegmentation = segmentations?.find(seg => seg.isActive);
-
- setToolsEnabled(activeSegmentation?.segmentCount > 0);
- });
-
- unsubscriptions.push(unsubscribe);
- });
-
- return () => {
- unsubscriptions.forEach(unsubscribe => unsubscribe());
- };
- }, [activeViewportId, viewports, segmentationService]);
-
- /**
- * Update the active tool when the toolbar state changes
- */
- useEffect(() => {
- const { unsubscribe } = toolbarService.subscribe(
- toolbarService.EVENTS.TOOL_BAR_STATE_MODIFIED,
- () => {
- updateActiveTool();
- }
- );
-
- return () => {
- unsubscribe();
- };
- }, [toolbarService, updateActiveTool]);
-
- const setToolActive = useCallback(
- toolName => {
- toolbarService.recordInteraction({
- groupId: 'SegmentationTools',
- itemId: 'Brush',
- interactionType: 'tool',
- commands: [
- {
- commandName: 'setToolActive',
- commandOptions: {
- toolName,
- },
- },
- ],
- });
-
- dispatch({ type: ACTIONS.SET_ACTIVE_TOOL, payload: toolName });
- },
- [toolbarService, dispatch]
- );
-
- const updateBrushSize = useCallback(
- (toolName, brushSize) => {
- toolGroupService.getToolGroupIds()?.forEach(toolGroupId => {
- segmentationUtils.setBrushSizeForToolGroup(toolGroupId, brushSize, toolName);
- });
- },
- [toolGroupService]
- );
-
- const onBrushSizeChange = useCallback(
- (valueAsStringOrNumber, toolCategory) => {
- const value = Number(valueAsStringOrNumber);
-
- _getToolNamesFromCategory(toolCategory).forEach(toolName => {
- updateBrushSize(toolName, value);
- });
-
- dispatch({
- type: ACTIONS.SET_TOOL_CONFIG,
- payload: {
- tool: toolCategory,
- config: { brushSize: value },
- },
- });
- },
- [toolGroupService, dispatch]
- );
-
- const handleRangeChange = useCallback(
- newRange => {
- if (
- newRange[0] === state.ThresholdBrush.thresholdRange[0] &&
- newRange[1] === state.ThresholdBrush.thresholdRange[1]
- ) {
- return;
- }
-
- const toolNames = _getToolNamesFromCategory('ThresholdBrush');
-
- toolNames.forEach(toolName => {
- toolGroupService.getToolGroupIds()?.forEach(toolGroupId => {
- const toolGroup = toolGroupService.getToolGroup(toolGroupId);
- toolGroup.setToolConfiguration(toolName, {
- strategySpecificConfiguration: {
- THRESHOLD_INSIDE_CIRCLE: {
- threshold: newRange,
- },
- },
- });
- });
- });
-
- dispatch({
- type: ACTIONS.SET_TOOL_CONFIG,
- payload: {
- tool: 'ThresholdBrush',
- config: { thresholdRange: newRange },
- },
- });
- },
- [toolGroupService, dispatch, state.ThresholdBrush.thresholdRange]
- );
-
- return (
- setToolActive('CircularBrush'),
- options: [
- {
- name: 'Radius (mm)',
- id: 'brush-radius',
- type: 'range',
- min: 0.01,
- max: 100,
- value: state.Brush.brushSize,
- step: 0.5,
- onChange: value => onBrushSizeChange(value, 'Brush'),
- },
- {
- name: 'Mode',
- type: 'radio',
- id: 'brush-mode',
- value: state.Brush.mode,
- values: [
- { value: 'CircularBrush', label: 'Circle' },
- { value: 'SphereBrush', label: 'Sphere' },
- ],
- onChange: value => setToolActive(value),
- },
- ],
- },
- {
- name: 'Eraser',
- icon: 'icon-tool-eraser',
- disabled: !toolsEnabled,
- active: state.activeTool === 'CircularEraser' || state.activeTool === 'SphereEraser',
- onClick: () => setToolActive('CircularEraser'),
- options: [
- {
- name: 'Radius (mm)',
- type: 'range',
- id: 'eraser-radius',
- min: 0.01,
- max: 100,
- value: state.Eraser.brushSize,
- step: 0.5,
- onChange: value => onBrushSizeChange(value, 'Eraser'),
- },
- {
- name: 'Mode',
- type: 'radio',
- id: 'eraser-mode',
- value: state.Eraser.mode,
- values: [
- { value: 'CircularEraser', label: 'Circle' },
- { value: 'SphereEraser', label: 'Sphere' },
- ],
- onChange: value => setToolActive(value),
- },
- ],
- },
- {
- name: 'Scissor',
- icon: 'icon-tool-scissor',
- disabled: !toolsEnabled,
- active:
- state.activeTool === 'CircleScissor' ||
- state.activeTool === 'RectangleScissor' ||
- state.activeTool === 'SphereScissor',
- onClick: () => setToolActive('CircleScissor'),
- options: [
- {
- name: 'Mode',
- type: 'radio',
- value: state.Scissors.mode,
- id: 'scissor-mode',
- values: [
- { value: 'CircleScissor', label: 'Circle' },
- { value: 'RectangleScissor', label: 'Rectangle' },
- { value: 'SphereScissor', label: 'Sphere' },
- ],
- onChange: value => setToolActive(value),
- },
- ],
- },
- {
- name: 'Threshold Tool',
- icon: 'icon-tool-threshold',
- disabled: !toolsEnabled,
- active:
- state.activeTool === 'ThresholdCircularBrush' ||
- state.activeTool === 'ThresholdSphereBrush',
- onClick: () => setToolActive('ThresholdCircularBrush'),
- options: [
- {
- name: 'Radius (mm)',
- id: 'threshold-radius',
- type: 'range',
- min: 0.01,
- max: 100,
- value: state.ThresholdBrush.brushSize,
- step: 0.5,
- onChange: value => onBrushSizeChange(value, 'ThresholdBrush'),
- },
- {
- name: 'Mode',
- type: 'radio',
- id: 'threshold-mode',
- value: state.activeTool,
- values: [
- { value: 'ThresholdCircularBrush', label: 'Circle' },
- { value: 'ThresholdSphereBrush', label: 'Sphere' },
- ],
- onChange: value => setToolActive(value),
- },
- {
- type: 'custom',
- children: () => {
- return (
-
- );
- },
- },
- ],
- },
- ]}
- />
- );
-}
-
-function _getToolNamesFromCategory(category) {
- let toolNames = [];
- switch (category) {
- case 'Brush':
- toolNames = ['CircularBrush', 'SphereBrush'];
- break;
- case 'Eraser':
- toolNames = ['CircularEraser', 'SphereEraser'];
- break;
- case 'ThresholdBrush':
- toolNames = ['ThresholdCircularBrush', 'ThresholdSphereBrush'];
- break;
- default:
- break;
- }
-
- return toolNames;
-}
-
-export default SegmentationToolbox;
diff --git a/plugins/ohifv3/extensions/monai-label/src/components/actions/ActiveLearning.tsx b/plugins/ohifv3/extensions/monai-label/src/components/actions/ActiveLearning.tsx
index dd0bd2fc4..e7546cb9e 100644
--- a/plugins/ohifv3/extensions/monai-label/src/components/actions/ActiveLearning.tsx
+++ b/plugins/ohifv3/extensions/monai-label/src/components/actions/ActiveLearning.tsx
@@ -146,6 +146,9 @@ export default class OptionTable extends BaseTab {
const image = this.props.viewConstants.SeriesInstanceUID;
+ debugger
+ const scalarData = labelmaps3D
+
const label = new Blob([labelmaps3D.scalarData], {
type: 'application/octet-stream',
});
diff --git a/plugins/ohifv3/extensions/monai-label/src/components/actions/SmartEdit.tsx b/plugins/ohifv3/extensions/monai-label/src/components/actions/SmartEdit.tsx
index ba607d19a..e1356274a 100644
--- a/plugins/ohifv3/extensions/monai-label/src/components/actions/SmartEdit.tsx
+++ b/plugins/ohifv3/extensions/monai-label/src/components/actions/SmartEdit.tsx
@@ -10,7 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
-
import React from 'react';
import ModelSelector from '../ModelSelector';
import BaseTab from './BaseTab';
@@ -38,7 +37,7 @@ export default class SmartEdit extends BaseTab {
this.props.servicesManager.services;
const added = segmentationService.EVENTS.SEGMENTATION_ADDED;
- const updated = segmentationService.EVENTS.SEGMENTATION_UPDATED;
+ const updated = segmentationService.EVENTS.SEGMENTATION_MODIFIED;
const removed = segmentationService.EVENTS.SEGMENTATION_REMOVED;
const subscriptions = [];
@@ -52,17 +51,28 @@ export default class SmartEdit extends BaseTab {
// get the first segmentation Todo: fix this to be active
const segmentation = segmentations[0];
- const { segments, activeSegmentIndex } = segmentation;
+ const { segmentationId } = segmentation;
+
+ // const selectedSegment = segments.find((segment) => segment.active);
+ const activeSegmentIndex= cornerstoneTools.segmentation.segmentIndex.getActiveSegmentIndex(segmentationId)
+
- const selectedSegment = segments[activeSegmentIndex];
+ if (!activeSegmentIndex) {
+ return;
+ }
- const color = selectedSegment.color;
+
+ const viewport = this.getActiveViewportInfo();
+ const { viewportOptions, viewportId } = viewport;
+
+ // const color = selectedSegment.color;
+ const color =
+ cornerstoneTools.segmentation.config.color.getSegmentIndexColor(
+ viewportId,
+ segmentationId,
+ activeSegmentIndex
+ ) || [0, 0, 0];
- // get the active viewport toolGroup
- const { viewports, activeViewportId } =
- viewportGridService.getState();
- const viewport = viewports.get(activeViewportId);
- const { viewportOptions } = viewport;
const toolGroupId = viewportOptions.toolGroupId;
toolGroupService.setToolConfiguration(toolGroupId, 'ProbeMONAILabel', {
@@ -77,6 +87,13 @@ export default class SmartEdit extends BaseTab {
};
}
+ getActiveViewportInfo = () => {
+ const { viewportGridService } = this.props.servicesManager.services;
+ const { viewports, activeViewportId } = viewportGridService.getState();
+ const viewport = viewports.get(activeViewportId);
+ return viewport;
+ }
+
componentWillUnmount() {
this.unsubscribe();
}
@@ -92,7 +109,10 @@ export default class SmartEdit extends BaseTab {
const image = viewConstants.SeriesInstanceUID;
const model = this.modelSelector.current.currentModel();
- const activeSegment = segmentationService.getActiveSegment();
+ const viewport = this.getActiveViewportInfo();
+ const { viewportId } = viewport;
+
+ const activeSegment = segmentationService.getActiveSegment(viewportId);
const segmentId = activeSegment.label;
if (segmentId && !this.state.segmentId) {
diff --git a/plugins/ohifv3/extensions/monai-label/src/components/w3.css b/plugins/ohifv3/extensions/monai-label/src/components/w3.css
deleted file mode 100644
index 3e78e3b2c..000000000
--- a/plugins/ohifv3/extensions/monai-label/src/components/w3.css
+++ /dev/null
@@ -1,235 +0,0 @@
-/* W3.CSS 4.15 December 2020 by Jan Egil and Borge Refsnes */
-html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}
-/* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */
-html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}
-article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item}
-audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline}
-audio:not([controls]){display:none;height:0}[hidden],template{display:none}
-a{background-color:transparent}a:active,a:hover{outline-width:0}
-abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}
-b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000}
-small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
-sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none}
-code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible}
-button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold}
-button,input{overflow:visible}button,select{text-transform:none}
-button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}
-button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}
-button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}
-fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}
-legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}
-[type=checkbox],[type=radio]{padding:0}
-[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}
-[type=search]{-webkit-appearance:textfield;outline-offset:-2px}
-[type=search]::-webkit-search-decoration{-webkit-appearance:none}
-::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}
-/* End extract */
-html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden}
-h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px}
-.w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace}
-h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px}
-hr{border:0;border-top:1px solid #eee;margin:20px 0}
-.w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit}
-.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc}
-.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1}
-.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1}
-.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center}
-.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top}
-.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px}
-.w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap}
-.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}
-.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
-.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none}
-.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none}
-.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%}
-.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none}
-.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block}
-.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s}
-.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%}
-.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc}
-.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer}
-.w3-dropdown-hover:hover .w3-dropdown-content{display:block}
-.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000}
-.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000}
-.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1}
-.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px}
-.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto}
-.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%}
-.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%}
-.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px}
-.w3-main,#main{transition:margin-left .4s}
-.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)}
-.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px}
-.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto}
-.w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0}
-.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left}
-.w3-bar .w3-button{white-space:normal}
-.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0}
-.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%}
-.w3-responsive{display:block;overflow-x:auto}
-.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before,
-.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both}
-.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%}
-.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%}
-.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%}
-.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%}
-@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%}
-.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%}
-.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}}
-@media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%}
-.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%}
-.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}}
-.w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px}
-.w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px}
-.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell}
-.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom}
-.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important}
-@media (max-width:1205px){.w3-auto{max-width:95%}}
-@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px}
-.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative}
-.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center}
-.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}}
-@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}}
-@media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}}
-@media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}}
-@media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}}
-.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0}
-.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2}
-.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0}
-.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0}
-.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)}
-.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)}
-.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)}
-.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
-.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
-.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none}
-.w3-display-position{position:absolute}
-.w3-circle{border-radius:50%}
-.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px}
-.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px}
-.w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px}
-.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px}
-.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word}
-.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%}
-.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)}
-.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)}
-.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}
-.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}}
-.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}}
-.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}}
-.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}}
-.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}}
-.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}}
-.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}}
-.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important}
-.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1}
-.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75}
-.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)}
-.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)}
-.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)}
-.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important}
-.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important}
-.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important}
-.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important}
-.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important}
-.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important}
-.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important}
-.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important}
-.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important}
-.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important}
-.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important}
-.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important}
-.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important}
-.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important}
-.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important}
-.w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important}
-.w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important}
-.w3-left{float:left!important}.w3-right{float:right!important}
-.w3-button:hover{color:#000!important;background-color:#ccc!important}
-.w3-transparent,.w3-hover-none:hover{background-color:transparent!important}
-.w3-hover-none:hover{box-shadow:none!important}
-/* Colors */
-.w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important}
-.w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important}
-.w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important}
-.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important}
-.w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important}
-.w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important}
-.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important}
-.w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important}
-.w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important}
-.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important}
-.w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important}
-.w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important}
-.w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important}
-.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important}
-.w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important}
-.w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important}
-.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important}
-.w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important}
-.w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important}
-.w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important}
-.w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important}
-.w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important}
-.w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important}
-.w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important}
-.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important}
-.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important}
-.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important}
-.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important}
-.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important}
-.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important}
-.w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important}
-.w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important}
-.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important}
-.w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important}
-.w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important}
-.w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important}
-.w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important}
-.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important}
-.w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important}
-.w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important}
-.w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important}
-.w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important}
-.w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important}
-.w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important}
-.w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important}
-.w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important}
-.w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important}
-.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important}
-.w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important}
-.w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important}
-.w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important}
-.w3-text-white,.w3-hover-text-white:hover{color:#fff!important}
-.w3-text-black,.w3-hover-text-black:hover{color:#000!important}
-.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important}
-.w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important}
-.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important}
-.w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important}
-.w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important}
-.w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important}
-.w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important}
-.w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important}
-.w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important}
-.w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important}
-.w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important}
-.w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important}
-.w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important}
-.w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important}
-.w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important}
-.w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important}
-.w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important}
-.w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important}
-.w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important}
-.w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important}
-.w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important}
-.w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important}
-.w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important}
-.w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important}
-.w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important}
-.w3-border-black,.w3-hover-border-black:hover{border-color:#000!important}
-.w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important}
-.w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important}
-.w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important}
-.w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important}
-.w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important}
diff --git a/plugins/ohifv3/extensions/monai-label/src/getCommandsModule.ts b/plugins/ohifv3/extensions/monai-label/src/getCommandsModule.ts
index a1f4c751a..d2868acc6 100644
--- a/plugins/ohifv3/extensions/monai-label/src/getCommandsModule.ts
+++ b/plugins/ohifv3/extensions/monai-label/src/getCommandsModule.ts
@@ -1,35 +1,14 @@
-import { ServicesManager, CommandsManager, ExtensionManager } from '@ohif/core';
-import {
- Enums,
-} from '@cornerstonejs/tools';
-
-export default function getCommandsModule({
- servicesManager,
- commandsManager,
- extensionManager,
-}: {
- servicesManager: ServicesManager;
- commandsManager: CommandsManager;
- extensionManager: ExtensionManager;
-}) {
- const {
- viewportGridService,
- toolGroupService,
- cineService,
- toolbarService,
- uiNotificationService,
- } = servicesManager.services;
+export default function getCommandsModule({ servicesManager }) {
+ const { uiNotificationService } = servicesManager.services;
const actions = {
setToolActive: ({ toolName }) => {
-
- uiNotificationService.show({
- title: 'MONAI Label probe',
- message:
- 'MONAI Label Probe Activated.',
- type: 'info',
- duration: 3000,
- });
+ uiNotificationService.show({
+ title: 'MONAI Label probe',
+ message: 'MONAI Label Probe Activated.',
+ type: 'info',
+ duration: 3000,
+ });
},
};
diff --git a/plugins/ohifv3/extensions/monai-label/src/index.tsx b/plugins/ohifv3/extensions/monai-label/src/index.tsx
index 5b3e76f6b..37578c659 100644
--- a/plugins/ohifv3/extensions/monai-label/src/index.tsx
+++ b/plugins/ohifv3/extensions/monai-label/src/index.tsx
@@ -5,53 +5,7 @@ import preRegistration from './init';
export default {
id,
-
preRegistration,
-
getPanelModule,
-
- getViewportModule: ({
- servicesManager,
- commandsManager,
- extensionManager,
- }) => {},
-
- getToolbarModule: ({
- servicesManager,
- commandsManager,
- extensionManager,
- }) => {},
-
- getLayoutTemplateModule: ({
- servicesManager,
- commandsManager,
- extensionManager,
- }) => {},
-
- getSopClassHandlerModule: ({
- servicesManager,
- commandsManager,
- extensionManager,
- }) => {},
-
- getHangingProtocolModule: ({
- servicesManager,
- commandsManager,
- extensionManager,
- }) => {},
-
getCommandsModule,
-
- getContextModule: ({
- servicesManager,
- commandsManager,
- extensionManager,
- }) => {},
-
- getDataSourcesModule: ({
- servicesManager,
- commandsManager,
- extensionManager,
- }) => {},
-
};
diff --git a/plugins/ohifv3/extensions/monai-label/src/init.ts b/plugins/ohifv3/extensions/monai-label/src/init.ts
index 58c3afdef..bee5f4836 100644
--- a/plugins/ohifv3/extensions/monai-label/src/init.ts
+++ b/plugins/ohifv3/extensions/monai-label/src/init.ts
@@ -1,7 +1,5 @@
-import {
- addTool,
-} from '@cornerstonejs/tools';
-import { Types } from '@ohif/core';
+import { addTool } from '@cornerstonejs/tools';
+import type { Types } from '@ohif/core';
import ProbeMONAILabelTool from './tools/ProbeMONAILabelTool';
/**
diff --git a/plugins/ohifv3/extensions/monai-label/src/tools/ProbeMONAILabelTool.ts b/plugins/ohifv3/extensions/monai-label/src/tools/ProbeMONAILabelTool.ts
index 8997271da..206caa175 100644
--- a/plugins/ohifv3/extensions/monai-label/src/tools/ProbeMONAILabelTool.ts
+++ b/plugins/ohifv3/extensions/monai-label/src/tools/ProbeMONAILabelTool.ts
@@ -1,4 +1,3 @@
-import { Types, metaData, utilities as csUtils } from '@cornerstonejs/core';
import { ProbeTool, annotation, drawing } from '@cornerstonejs/tools';
const { getAnnotations } = annotation.state;
@@ -37,18 +36,15 @@ export default class ProbeMONAILabelTool extends ProbeTool {
return renderStatus;
}
- const targetId = this.getTargetId(viewport);
- const renderingEngine = viewport.getRenderingEngine();
-
- const styleSpecifier: StyleSpecifier = {
+ const styleSpecifier = {
toolGroupId: this.toolGroupId,
toolName: this.getToolName(),
viewportId: enabledElement.viewport.id,
};
for (let i = 0; i < annotations.length; i++) {
- const annotation = annotations[i] as ProbeAnnotation;
- const annotationUID = annotation.annotationUID;
+ const annotation = annotations[i];
+ const annotationUID = annotation.annotationUID as string;
const data = annotation.data;
const point = data.handles.points[0];
const canvasCoordinates = viewport.worldToCanvas(point);
diff --git a/plugins/ohifv3/modes/monai-label/package.json b/plugins/ohifv3/modes/monai-label/package.json
index ecbae9558..171a49d4b 100644
--- a/plugins/ohifv3/modes/monai-label/package.json
+++ b/plugins/ohifv3/modes/monai-label/package.json
@@ -30,7 +30,7 @@
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
},
"peerDependencies": {
- "@ohif/core": "^3.0.0"
+ "@ohif/core": "^3.9.0-beta.101"
},
"dependencies": {
"@babel/runtime": "^7.20.13"
diff --git a/plugins/ohifv3/modes/monai-label/src/index.tsx b/plugins/ohifv3/modes/monai-label/src/index.tsx
index f832dd869..e4adb9aa6 100644
--- a/plugins/ohifv3/modes/monai-label/src/index.tsx
+++ b/plugins/ohifv3/modes/monai-label/src/index.tsx
@@ -3,28 +3,34 @@ import toolbarButtons from './toolbarButtons.js';
import { id } from './id.js';
import initToolGroups from './initToolGroups.js';
+
+const monailabel = {
+ monaiLabel: '@ohif/extension-monai-label.panelModule.monailabel',
+}
+
+
const ohif = {
layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout',
sopClassHandler: '@ohif/extension-default.sopClassHandlerModule.stack',
hangingProtocol: '@ohif/extension-default.hangingProtocolModule.default',
leftPanel: '@ohif/extension-default.panelModule.seriesList',
+ rightPanel: '@ohif/extension-default.panelModule.measure',
};
-const monailabel = {
- monaiLabel: '@ohif/extension-monai-label.panelModule.monailabel',
-}
-
const cornerstone = {
viewport: '@ohif/extension-cornerstone.viewportModule.cornerstone',
+ panelTool:
+ '@ohif/extension-cornerstone.panelModule.panelSegmentationWithTools',
};
-const dicomSeg = {
+const segmentation = {
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',
};
+
+
/**
* Just two dependencies to be able to render a viewport with panels in order
* to make sure that the mode is working.
@@ -67,42 +73,12 @@ function modeFactory({ modeConfiguration }) {
// Init Default and SR ToolGroups
initToolGroups(extensionManager, toolGroupService, commandsManager);
+ toolbarService.addButtons(toolbarButtons);
// init customizations
customizationService.addModeCustomizations([
'@ohif/extension-test.customizationModule.custom-context-menu',
]);
- 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',
@@ -115,6 +91,13 @@ function modeFactory({ modeConfiguration }) {
'Crosshairs',
'MoreTools',
]);
+
+ toolbarService.createButtonSection('segmentationToolbox', [
+ 'BrushTools',
+ 'Shapes',
+ ]);
+
+
},
onModeExit: ({ servicesManager }) => {
const {
@@ -122,8 +105,12 @@ function modeFactory({ modeConfiguration }) {
syncGroupService,
segmentationService,
cornerstoneViewportService,
+ uiDialogService,
+ uiModalService,
} = servicesManager.services;
+ uiDialogService.dismissAll();
+ uiModalService.hide();
toolGroupService.destroy();
syncGroupService.destroy();
segmentationService.destroy();
@@ -141,7 +128,7 @@ function modeFactory({ modeConfiguration }) {
isValidMode: function ({ modalities }) {
const modalities_list = modalities.split('\\');
const isValid =
- modalities_list.includes('CT') || modalities_list.includes('MR');
+ modalities_list.includes('CT') || modalities_list.includes('MR');
// Only CT or MR modalities
return isValid;
},
@@ -174,8 +161,8 @@ function modeFactory({ modeConfiguration }) {
displaySetsToDisplay: [ohif.sopClassHandler],
},
{
- namespace: dicomSeg.viewport,
- displaySetsToDisplay: [dicomSeg.sopClassHandler],
+ namespace: segmentation.viewport,
+ displaySetsToDisplay: [segmentation.sopClassHandler],
},
],
},
@@ -190,7 +177,7 @@ function modeFactory({ modeConfiguration }) {
// hangingProtocol: [''],
/** SopClassHandlers used by the mode */
sopClassHandlers: [
- dicomSeg.sopClassHandler,
+ segmentation.sopClassHandler,
ohif.sopClassHandler,
] /** hotkeys for mode */,
hotkeys: [...hotkeys.defaults.hotkeyBindings],
diff --git a/plugins/ohifv3/modes/monai-label/src/initToolGroups.js b/plugins/ohifv3/modes/monai-label/src/initToolGroups.js
index 81bc09eb6..35ab84861 100644
--- a/plugins/ohifv3/modes/monai-label/src/initToolGroups.js
+++ b/plugins/ohifv3/modes/monai-label/src/initToolGroups.js
@@ -1,34 +1,18 @@
-const brushInstanceNames = {
- CircularBrush: 'CircularBrush',
- CircularEraser: 'CircularEraser',
- SphereBrush: 'SphereBrush',
- SphereEraser: 'SphereEraser',
- ThresholdCircularBrush: 'ThresholdCircularBrush',
- ThresholdSphereBrush: 'ThresholdSphereBrush',
+const colours = {
+ 'viewport-0': 'rgb(200, 0, 0)',
+ 'viewport-1': 'rgb(200, 200, 0)',
+ 'viewport-2': 'rgb(0, 200, 0)',
};
-const brushStrategies = {
- [brushInstanceNames.CircularBrush]: 'FILL_INSIDE_CIRCLE',
- [brushInstanceNames.CircularEraser]: 'ERASE_INSIDE_CIRCLE',
- [brushInstanceNames.SphereBrush]: 'FILL_INSIDE_SPHERE',
- [brushInstanceNames.SphereEraser]: 'ERASE_INSIDE_SPHERE',
- [brushInstanceNames.ThresholdCircularBrush]: 'THRESHOLD_INSIDE_CIRCLE',
- [brushInstanceNames.ThresholdSphereBrush]: 'THRESHOLD_INSIDE_SPHERE',
+const colorsByOrientation = {
+ axial: 'rgb(200, 0, 0)',
+ sagittal: 'rgb(200, 200, 0)',
+ coronal: 'rgb(0, 200, 0)',
};
-function initDefaultToolGroup(
- extensionManager,
- toolGroupService,
- commandsManager,
- toolGroupId
-) {
- const utilityModule = extensionManager.getModuleEntry(
- '@ohif/extension-cornerstone.utilityModule.tools'
- );
-
+function createTools(utilityModule) {
const { toolNames, Enums } = utilityModule.exports;
-
- const tools = {
+ return {
active: [
{
toolName: toolNames.WindowLevel,
@@ -42,64 +26,100 @@ function initDefaultToolGroup(
toolName: toolNames.Zoom,
bindings: [{ mouseButton: Enums.MouseBindings.Secondary }],
},
- { toolName: toolNames.StackScrollMouseWheel, bindings: [] },
+ {
+ toolName: toolNames.StackScroll,
+ bindings: [{ mouseButton: Enums.MouseBindings.Wheel }],
+ },
],
passive: [
- { toolName: toolNames.CircleScissors },
- { toolName: toolNames.RectangleScissors },
- { toolName: toolNames.SphereScissors },
{
- toolName: brushInstanceNames.CircularBrush,
+ toolName: 'CircularBrush',
parentTool: 'Brush',
configuration: {
- activeStrategy: brushStrategies.CircularBrush,
+ activeStrategy: 'FILL_INSIDE_CIRCLE',
},
},
{
- toolName: brushInstanceNames.CircularEraser,
+ toolName: 'CircularEraser',
parentTool: 'Brush',
configuration: {
- activeStrategy: brushStrategies.CircularEraser,
+ activeStrategy: 'ERASE_INSIDE_CIRCLE',
},
},
{
- toolName: brushInstanceNames.SphereEraser,
+ toolName: 'SphereBrush',
parentTool: 'Brush',
configuration: {
- activeStrategy: brushStrategies.SphereEraser,
+ activeStrategy: 'FILL_INSIDE_SPHERE',
},
},
{
- toolName: brushInstanceNames.SphereBrush,
+ toolName: 'SphereEraser',
parentTool: 'Brush',
configuration: {
- activeStrategy: brushStrategies.SphereBrush,
+ activeStrategy: 'ERASE_INSIDE_SPHERE',
},
},
{
- toolName: brushInstanceNames.ThresholdCircularBrush,
+ toolName: 'ThresholdCircularBrush',
parentTool: 'Brush',
configuration: {
- activeStrategy: brushStrategies.ThresholdCircularBrush,
+ activeStrategy: 'THRESHOLD_INSIDE_CIRCLE',
},
},
{
- toolName: brushInstanceNames.ThresholdSphereBrush,
+ toolName: 'ThresholdSphereBrush',
parentTool: 'Brush',
configuration: {
- activeStrategy: brushStrategies.ThresholdSphereBrush,
+ activeStrategy: 'THRESHOLD_INSIDE_SPHERE',
},
},
+ {
+ toolName: 'ThresholdCircularBrushDynamic',
+ parentTool: 'Brush',
+ configuration: {
+ activeStrategy: 'THRESHOLD_INSIDE_CIRCLE',
+ // preview: {
+ // enabled: true,
+ // },
+ strategySpecificConfiguration: {
+ // to use the use the center segment index to determine
+ // if inside -> same segment, if outside -> eraser
+ // useCenterSegmentIndex: true,
+ THRESHOLD: {
+ isDynamic: true,
+ dynamicRadius: 3,
+ },
+ },
+ },
+ },
+ { toolName: 'ProbeMONAILabel' },
+ { toolName: toolNames.CircleScissors },
+ { toolName: toolNames.RectangleScissors },
+ { toolName: toolNames.SphereScissors },
{ toolName: toolNames.StackScroll },
{ toolName: toolNames.Magnify },
- { toolName: toolNames.SegmentationDisplay },
- { toolName: 'ProbeMONAILabel' },
+ { toolName: toolNames.WindowLevelRegion },
+
+ { toolName: toolNames.UltrasoundDirectional },
+ ],
+ disabled: [
+ { toolName: toolNames.ReferenceLines },
+ { toolName: toolNames.AdvancedMagnify },
],
- // enabled
- // disabled
- disabled: [{ toolName: toolNames.ReferenceLines }],
};
+}
+function initDefaultToolGroup(
+ extensionManager,
+ toolGroupService,
+ commandsManager,
+ toolGroupId
+) {
+ const utilityModule = extensionManager.getModuleEntry(
+ '@ohif/extension-cornerstone.utilityModule.tools'
+ );
+ const tools = createTools(utilityModule);
toolGroupService.createToolGroupAndAddTools(toolGroupId, tools);
}
@@ -107,93 +127,72 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) {
const utilityModule = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone.utilityModule.tools'
);
+ const servicesManager = extensionManager._servicesManager;
+ const { cornerstoneViewportService } = servicesManager.services;
+ const tools = createTools(utilityModule);
+
+ tools.disabled.push(
+ {
+ toolName: utilityModule.exports.toolNames.Crosshairs,
+ configuration: {
+ viewportIndicators: true,
+ viewportIndicatorsConfig: {
+ circleRadius: 5,
+ xOffset: 0.95,
+ yOffset: 0.05,
+ },
+ disableOnPassive: true,
+ autoPan: {
+ enabled: false,
+ panSize: 10,
+ },
+ getReferenceLineColor: (viewportId) => {
+ const viewportInfo =
+ cornerstoneViewportService.getViewportInfo(viewportId);
+ const viewportOptions = viewportInfo?.viewportOptions;
+ if (viewportOptions) {
+ return (
+ colours[viewportOptions.id] ||
+ colorsByOrientation[viewportOptions.orientation] ||
+ '#0c0'
+ );
+ } else {
+ console.warn('missing viewport?', viewportId);
+ return '#0c0';
+ }
+ },
+ },
+ },
+ { toolName: utilityModule.exports.toolNames.ReferenceLines }
+ );
+ 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.WindowLevel,
+ toolName: toolNames.TrackballRotateTool,
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.CircleScissors },
- { toolName: toolNames.RectangleScissors },
- { toolName: toolNames.SphereScissors },
- {
- toolName: brushInstanceNames.CircularBrush,
- parentTool: 'Brush',
- configuration: {
- activeStrategy: brushStrategies.CircularBrush,
- },
- },
- {
- toolName: brushInstanceNames.CircularEraser,
- parentTool: 'Brush',
- configuration: {
- activeStrategy: brushStrategies.CircularEraser,
- },
- },
- {
- toolName: brushInstanceNames.SphereEraser,
- parentTool: 'Brush',
- configuration: {
- activeStrategy: brushStrategies.SphereEraser,
- },
- },
{
- toolName: brushInstanceNames.SphereBrush,
- parentTool: 'Brush',
- configuration: {
- activeStrategy: brushStrategies.SphereBrush,
- },
- },
- {
- toolName: brushInstanceNames.ThresholdCircularBrush,
- parentTool: 'Brush',
- configuration: {
- activeStrategy: brushStrategies.ThresholdCircularBrush,
- },
- },
- {
- toolName: brushInstanceNames.ThresholdSphereBrush,
- parentTool: 'Brush',
- configuration: {
- activeStrategy: brushStrategies.ThresholdSphereBrush,
- },
- },
- { toolName: toolNames.SegmentationDisplay },
- { toolName: 'ProbeMONAILabel' },
- { toolName: 'ProbeMONAILabel' },
- ],
- disabled: [
- {
- toolName: toolNames.Crosshairs,
- configuration: {
- viewportIndicators: false,
- autoPan: {
- enabled: false,
- panSize: 10,
- },
- },
+ toolName: toolNames.Pan,
+ bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }],
},
- { toolName: toolNames.ReferenceLines },
],
- // enabled
- // disabled
};
- toolGroupService.createToolGroupAndAddTools('mpr', tools);
+ toolGroupService.createToolGroupAndAddTools('volume3d', tools);
}
function initToolGroups(extensionManager, toolGroupService, commandsManager) {
@@ -204,6 +203,7 @@ function initToolGroups(extensionManager, toolGroupService, commandsManager) {
'default'
);
initMPRToolGroup(extensionManager, toolGroupService, commandsManager);
+ initVolume3DToolGroup(extensionManager, toolGroupService);
}
export default initToolGroups;
diff --git a/plugins/ohifv3/modes/monai-label/src/toolbarButtons.js b/plugins/ohifv3/modes/monai-label/src/toolbarButtons.js
index 92de37e89..5a6945096 100644
--- a/plugins/ohifv3/modes/monai-label/src/toolbarButtons.js
+++ b/plugins/ohifv3/modes/monai-label/src/toolbarButtons.js
@@ -1,608 +1,205 @@
-// 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';
+import type { Button } from '@ohif/core/types';
-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,
- };
-}
-
-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 toolGroupIds = ['default', 'mpr', 'SRToolGroup'];
-
-/**
- * Creates an array of 'setToolActive' commands for the given toolName - one for
- * each toolGroupId specified in toolGroupIds.
- * @param {string} toolName
- * @returns {Array} an array of 'setToolActive' commands
- */
-function _createSetToolActiveCommands(toolName) {
- const temp = toolGroupIds.map(toolGroupId => ({
- commandName: 'setToolActive',
- commandOptions: {
- toolGroupId,
- toolName,
- },
- context: 'CORNERSTONE',
- }));
- return temp;
-}
-
-const toolbarButtons = [
- // Measurement
+const toolbarButtons: Button[] = [
{
- id: 'MeasurementTools',
- type: 'ohif.splitButton',
+ id: 'BrushTools',
+ uiType: 'ohif.buttonGroup',
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',
- },
+ groupId: 'BrushTools',
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',
- [
+ {
+ id: 'Brush',
+ icon: 'icon-tool-brush',
+ label: 'Brush',
+ evaluate: {
+ name: 'evaluate.cornerstone.segmentation',
+ toolNames: ['CircularBrush', 'SphereBrush'],
+ disabledText: 'Create new segmentation to enable this tool.',
+ },
+ options: [
{
- commandName: 'setToolActive',
- commandOptions: {
- toolName: 'ArrowAnnotate',
+ name: 'Radius (mm)',
+ id: 'brush-radius',
+ type: 'range',
+ min: 0.5,
+ max: 99.5,
+ step: 0.5,
+ value: 25,
+ commands: {
+ commandName: 'setBrushSize',
+ commandOptions: { toolNames: ['CircularBrush', 'SphereBrush'] },
},
- context: 'CORNERSTONE',
},
{
- commandName: 'setToolActive',
- commandOptions: {
- toolName: 'SRArrowAnnotate',
- toolGroupId: 'SRToolGroup',
- },
- context: 'CORNERSTONE',
+ name: 'Shape',
+ type: 'radio',
+ id: 'brush-mode',
+ value: 'CircularBrush',
+ values: [
+ { value: 'CircularBrush', label: 'Circle' },
+ { value: 'SphereBrush', label: 'Sphere' },
+ ],
+ commands: 'setToolActiveToolbar',
},
],
- 'Arrow Annotate'
- ),
- _createToolButton(
- 'EllipticalROI',
- 'tool-elipse',
- 'Ellipse',
- [
- {
- commandName: 'setToolActive',
- commandOptions: {
- toolName: 'EllipticalROI',
- },
- context: 'CORNERSTONE',
- },
- {
- commandName: 'setToolActive',
- commandOptions: {
- toolName: 'SREllipticalROI',
- toolGroupId: 'SRToolGroup',
- },
- context: 'CORNERSTONE',
+ },
+ {
+ id: 'Eraser',
+ icon: 'icon-tool-eraser',
+ label: 'Eraser',
+ evaluate: {
+ name: 'evaluate.cornerstone.segmentation',
+ toolNames: ['CircularEraser', 'SphereEraser'],
+ },
+ options: [
+ {
+ name: 'Radius (mm)',
+ id: 'eraser-radius',
+ type: 'range',
+ min: 0.5,
+ max: 99.5,
+ step: 0.5,
+ value: 25,
+ commands: {
+ commandName: 'setBrushSize',
+ commandOptions: {
+ toolNames: ['CircularEraser', 'SphereEraser'],
+ },
+ },
+ },
+ {
+ name: 'Shape',
+ type: 'radio',
+ id: 'eraser-mode',
+ value: 'CircularEraser',
+ values: [
+ { value: 'CircularEraser', label: 'Circle' },
+ { value: 'SphereEraser', label: 'Sphere' },
+ ],
+ commands: 'setToolActiveToolbar',
},
],
- 'Ellipse Tool'
- ),
- _createToolButton(
- 'CircleROI',
- 'tool-circle',
- 'Circle',
- [
- {
- commandName: 'setToolActive',
- commandOptions: {
- toolName: 'CircleROI',
+ },
+ {
+ id: 'Threshold',
+ icon: 'icon-tool-threshold',
+ label: 'Threshold Tool',
+ evaluate: {
+ name: 'evaluate.cornerstone.segmentation',
+ toolNames: ['ThresholdCircularBrush', 'ThresholdSphereBrush'],
+ },
+ options: [
+ {
+ name: 'Radius (mm)',
+ id: 'threshold-radius',
+ type: 'range',
+ min: 0.5,
+ max: 99.5,
+ step: 0.5,
+ value: 25,
+ commands: {
+ commandName: 'setBrushSize',
+ commandOptions: {
+ toolNames: [
+ 'ThresholdCircularBrush',
+ 'ThresholdSphereBrush',
+ 'ThresholdCircularBrushDynamic',
+ ],
+ },
},
- context: 'CORNERSTONE',
},
+
{
- commandName: 'setToolActive',
- commandOptions: {
- toolName: 'SRCircleROI',
- toolGroupId: 'SRToolGroup',
+ name: 'Threshold',
+ type: 'radio',
+ id: 'dynamic-mode',
+ value: 'ThresholdRange',
+ values: [
+ { value: 'ThresholdDynamic', label: 'Dynamic' },
+ { value: 'ThresholdRange', label: 'Range' },
+ ],
+ commands: ({ value, commandsManager, options }) => {
+ if (value === 'ThresholdDynamic') {
+ commandsManager.run('setToolActive', {
+ toolName: 'ThresholdCircularBrushDynamic',
+ });
+
+ return;
+ }
+
+ // 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',
+ type: 'radio',
+ id: 'threshold-shape',
+ value: 'ThresholdCircularBrush',
+ values: [
+ { value: 'ThresholdCircularBrush', label: 'Circle' },
+ { value: 'ThresholdSphereBrush', label: 'Sphere' },
+ ],
+ condition: ({ options }) =>
+ options.find((option) => option.id === 'dynamic-mode').value ===
+ 'ThresholdRange',
+ commands: 'setToolActiveToolbar',
+ },
+ {
+ name: 'ThresholdRange',
+ type: 'double-range',
+ id: 'threshold-range',
+ min: -1000,
+ max: 1000,
+ step: 1,
+ value: [100, 600],
+ condition: ({ options }) =>
+ options.find((option) => option.id === 'dynamic-mode').value ===
+ 'ThresholdRange',
+ commands: {
+ commandName: 'setThresholdRange',
+ commandOptions: {
+ toolNames: ['ThresholdCircularBrush', 'ThresholdSphereBrush'],
+ },
},
- context: 'CORNERSTONE',
},
],
- 'Circle Tool'
- ),
- ],
- },
- },
- // Zoom..
- {
- id: 'Zoom',
- type: 'ohif.radioGroup',
- props: {
- type: 'tool',
- icon: 'tool-zoom',
- label: 'Zoom',
- commands: _createSetToolActiveCommands('Zoom'),
- },
- },
- // 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: _createSetToolActiveCommands('Pan'),
- },
- },
- {
- id: 'Capture',
- type: 'ohif.action',
- props: {
- icon: 'tool-capture',
- label: 'Capture',
- type: 'action',
- commands: [
- {
- commandName: 'showDownloadViewportModal',
- commandOptions: {},
- context: 'CORNERSTONE',
},
],
},
},
{
- id: 'Layout',
- type: 'ohif.layoutSelector',
+ id: 'Shapes',
+ uiType: 'ohif.radioGroup',
props: {
- rows: 3,
- columns: 3,
- },
- },
- {
- id: 'MPR',
- type: 'ohif.action',
- props: {
- type: 'toggle',
- icon: 'icon-mpr',
- label: 'MPR',
- commands: [
- {
- commandName: 'toggleHangingProtocol',
- commandOptions: {
- protocolId: 'mpr',
- },
- context: 'DEFAULT',
- },
- ],
- },
- },
- {
- id: 'Crosshairs',
- type: 'ohif.radioGroup',
- props: {
- type: 'tool',
- icon: 'tool-crosshair',
- label: 'Crosshairs',
- commands: [
+ label: 'Shapes',
+ evaluate: {
+ name: 'evaluate.cornerstone.segmentation',
+ toolNames: ['CircleScissor', 'SphereScissor', 'RectangleScissor'],
+ },
+ icon: 'icon-tool-shape',
+ options: [
{
- commandName: 'setToolActive',
- commandOptions: {
- toolName: 'Crosshairs',
- toolGroupId: 'mpr',
- },
- context: 'CORNERSTONE',
+ name: 'Shape',
+ type: 'radio',
+ value: 'CircleScissor',
+ id: 'shape-mode',
+ values: [
+ { value: 'CircleScissor', label: 'Circle' },
+ { value: 'SphereScissor', label: 'Sphere' },
+ { value: 'RectangleScissor', label: 'Rectangle' },
+ ],
+ commands: 'setToolActiveToolbar',
},
],
},
},
- // 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'
- ),
-
- // Next two tools can be added once icons are added
- // _createToolButton(
- // 'Cobb Angle',
- // 'tool-cobb-angle',
- // 'Cobb Angle',
- // [
- // {
- // commandName: 'setToolActive',
- // commandOptions: {
- // toolName: 'CobbAngle',
- // },
- // context: 'CORNERSTONE',
- // },
- // ],
- // 'Cobb Angle'
- // ),
- // _createToolButton(
- // 'Planar Freehand ROI',
- // 'tool-freehand',
- // 'PlanarFreehandROI',
- // [
- // {
- // commandName: 'setToolActive',
- // commandOptions: {
- // toolName: 'PlanarFreehandROI',
- // },
- // context: 'CORNERSTONE',
- // },
- // ],
- // 'Planar Freehand ROI'
- // ),
- _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'
- ),
- _createToolButton(
- 'CalibrationLine',
- 'tool-calibration',
- 'Calibration',
- [
- {
- commandName: 'setToolActive',
- commandOptions: {
- toolName: 'CalibrationLine',
- },
- context: 'CORNERSTONE',
- },
- ],
- 'Calibration Line'
- ),
- _createActionButton(
- 'TagBrowser',
- 'list-bullets',
- 'Dicom Tag Browser',
- [
- {
- commandName: 'openDICOMTagViewer',
- commandOptions: {},
- context: 'DEFAULT',
- },
- ],
- 'Dicom Tag Browser'
- ),
- ],
- },
- },
];
export default toolbarButtons;