feat(cst): Add new command to get nearby annotation tools (#3327)

* feat(cst): Add new command to get nearby annotation tools
This commit adds a new command `getNearbyAnnotation` to the `commandsModule.ts` file that identifies nearby annotation tools excluding Crosshairs and ReferenceLines. It also removes an unused mapping to `Crosshairs` in `initMeasurementService.js` and changes the command run in `findNearbyToolData.ts` to `getNearbyAnnotation`.

* perf(cornerstone): Improve performance by optimizing tools

Removes unnecessary imports to improve app's performance. Changes how annotations are detected on the `commandsModule.js` file by fetching the `isAnnotation` property of the tool instance if available. Updates `CrosshairsTool` and `ReferenceLinesTool` to not be annotations anymore. Adjusts the `localhost` URL ports for the `dcm4chee-arc` service interface on `local_dcm4chee.js` to allow for more efficient server communication.

* feat(cornerstone): Add CornerstoneServices type and ToolGroupService.getToolGroup to get tool group by ID or active viewport

This commit introduces the new CornerstoneServices interface to the code and adds the ToolGroupService.getToolGroup method, which can retrieve a specific tool group by ID or from the active viewport. The older _getToolGroup method has also been removed from commandsModule. When no tool group ID is provided, this method now retrieves the tool group from the currently active viewport with the help of getActiveViewportEnabledElement. Additionally, the required reference to @ohif/core has been removed.
This commit is contained in:
Alireza 2023-04-28 10:14:14 -04:00 committed by GitHub
parent fe7fa6e5bf
commit c9d3c08cb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 90 additions and 68 deletions

View File

@ -10,7 +10,6 @@ import {
utilities as cstUtils,
ReferenceLinesTool,
} from '@cornerstonejs/tools';
import { ServicesManager } from '@ohif/core';
import CornerstoneViewportDownloadForm from './utils/CornerstoneViewportDownloadForm';
import callInputDialog from './utils/callInputDialog';
@ -18,6 +17,7 @@ import { setColormap } from './utils/colormap/transferFunctionHelpers';
import toggleStackImageSync from './utils/stackSync/toggleStackImageSync';
import { getFirstAnnotationSelected } from './utils/measurementServiceMappings/utils/selection';
import getActiveViewportEnabledElement from './utils/getActiveViewportEnabledElement';
import { CornerstoneServices } from './types';
function commandsModule({ servicesManager, commandsManager }) {
const {
@ -28,51 +28,14 @@ function commandsModule({ servicesManager, commandsManager }) {
uiDialogService,
cornerstoneViewportService,
uiNotificationService,
customizationService,
measurementService,
hangingProtocolService,
} = (servicesManager as ServicesManager).services;
} = servicesManager.services as CornerstoneServices;
const { measurementServiceSource } = this;
function _getActiveViewportEnabledElement() {
return getActiveViewportEnabledElement(viewportGridService);
}
function _getToolGroup(toolGroupId) {
let toolGroupIdToUse = toolGroupId;
if (!toolGroupIdToUse) {
// Use the active viewport's tool group if no tool group id is provided
const enabledElement = _getActiveViewportEnabledElement();
if (!enabledElement) {
return;
}
const { renderingEngineId, viewportId } = enabledElement;
const toolGroup = ToolGroupManager.getToolGroupForViewport(
viewportId,
renderingEngineId
);
if (!toolGroup) {
console.warn(
'No tool group found for viewportId:',
viewportId,
'and renderingEngineId:',
renderingEngineId
);
return;
}
toolGroupIdToUse = toolGroup.id;
}
const toolGroup = toolGroupService.getToolGroup(toolGroupIdToUse);
return toolGroup;
}
const actions = {
/**
* Generates the selector props for the context menu, specific to
@ -127,6 +90,36 @@ function commandsModule({ servicesManager, commandsManager }) {
cstUtils.getAnnotationNearPoint(element, canvasCoordinates)
);
},
getNearbyAnnotation({ element, canvasCoordinates }) {
const nearbyToolData = actions.getNearbyToolData({
nearbyToolData: null,
element,
canvasCoordinates,
});
const isAnnotation = toolName => {
const enabledElement = getEnabledElement(element);
if (!enabledElement) {
return;
}
const { renderingEngineId, viewportId } = enabledElement;
const toolGroup = ToolGroupManager.getToolGroupForViewport(
viewportId,
renderingEngineId
);
const toolInstance = toolGroup.getToolInstance(toolName);
return toolInstance?.constructor?.isAnnotation ?? true;
};
return nearbyToolData?.metadata?.toolName &&
isAnnotation(nearbyToolData.metadata.toolName)
? nearbyToolData
: null;
},
// Measurement tool commands:
@ -298,7 +291,7 @@ function commandsModule({ servicesManager, commandsManager }) {
setToolActive: ({ toolName, toolGroupId = null }) => {
if (toolName === 'Crosshairs') {
const activeViewportToolGroup = _getToolGroup(null);
const activeViewportToolGroup = toolGroupService.getToolGroup(null);
if (!activeViewportToolGroup._toolInstances.Crosshairs) {
uiNotificationService.show({
@ -317,7 +310,7 @@ function commandsModule({ servicesManager, commandsManager }) {
viewports: [],
};
const toolGroup = _getToolGroup(toolGroupId);
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
const toolGroupViewportIds = toolGroup?.getViewportIds?.();
// if toolGroup has been destroyed, or its viewports have been removed
@ -635,6 +628,11 @@ function commandsModule({ servicesManager, commandsManager }) {
storeContexts: [],
options: {},
},
getNearbyAnnotation: {
commandFn: actions.getNearbyAnnotation,
storeContexts: [],
options: {},
},
deleteMeasurement: {
commandFn: actions.deleteMeasurement,

View File

@ -30,6 +30,9 @@ import {
import CalibrationLineTool from './tools/CalibrationLineTool';
export default function initCornerstoneTools(configuration = {}) {
CrosshairsTool.isAnnotation = false;
ReferenceLinesTool.isAnnotation = false;
init(configuration);
addTool(PanTool);
addTool(WindowLevelTool);

View File

@ -49,20 +49,6 @@ const initMeasurementService = (
Length.toMeasurement
);
measurementService.addMapping(
csTools3DVer1MeasurementSource,
'Crosshairs',
Length.matchingCriteria,
() => {
console.warn('Crosshairs mapping not implemented.');
return {};
},
() => {
console.warn('Crosshairs mapping not implemented.');
return {};
}
);
measurementService.addMapping(
csTools3DVer1MeasurementSource,
'Bidirectional',

View File

@ -1,6 +1,7 @@
import { ToolGroupManager, Enums, Types } from '@cornerstonejs/tools';
import { Types as OhifTypes, pubSubServiceInterface } from '@ohif/core';
import getActiveViewportEnabledElement from '../../utils/getActiveViewportEnabledElement';
const EVENTS = {
VIEWPORT_ADDED: 'event::cornerstone::toolgroupservice:viewportadded',
@ -39,20 +40,56 @@ export default class ToolGroupService {
EVENTS: { [key: string]: string };
constructor(serviceManager) {
const { cornerstoneViewportService } = serviceManager.services;
const {
cornerstoneViewportService,
viewportGridService,
} = serviceManager.services;
this.cornerstoneViewportService = cornerstoneViewportService;
this.viewportGridService = viewportGridService;
this.listeners = {};
this.EVENTS = EVENTS;
Object.assign(this, pubSubServiceInterface);
}
/**
* Returns the cornerstone ToolGroup for a given toolGroup UID
* @param {string} toolGroupId - The toolGroup uid
* @returns {IToolGroup} - The toolGroup
* Retrieves a tool group from the ToolGroupManager by tool group ID.
* If no tool group ID is provided, it retrieves the tool group of the active viewport.
* @param toolGroupId - Optional ID of the tool group to retrieve.
* @returns The tool group or undefined if it is not found.
*/
public getToolGroup(toolGroupId: string): Types.IToolGroup | void {
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId);
public getToolGroup(toolGroupId?: string): Types.IToolGroup | void {
let toolGroupIdToUse = toolGroupId;
if (!toolGroupIdToUse) {
// Use the active viewport's tool group if no tool group id is provided
const enabledElement = getActiveViewportEnabledElement(
this.viewportGridService
);
if (!enabledElement) {
return;
}
const { renderingEngineId, viewportId } = enabledElement;
const toolGroup = ToolGroupManager.getToolGroupForViewport(
viewportId,
renderingEngineId
);
if (!toolGroup) {
console.warn(
'No tool group found for viewportId:',
viewportId,
'and renderingEngineId:',
renderingEngineId
);
return;
}
toolGroupIdToUse = toolGroup.id;
}
const toolGroup = ToolGroupManager.getToolGroup(toolGroupIdToUse);
return toolGroup;
}

View File

@ -11,7 +11,7 @@ export const findNearbyToolData = (commandsManager, evt) => {
}
const { element, currentPoints } = evt.detail;
return commandsManager.runCommand(
'getNearbyToolData',
'getNearbyAnnotation',
{
element,
canvasCoordinates: currentPoints?.canvas,

View File

@ -508,7 +508,6 @@ class MeasurementService extends PubSubService {
if (!this._isValidSource(source)) {
throw new Error('Invalid source.');
}
if (!annotationType) {
throw new Error('No source annotationType provided.');
}
@ -572,7 +571,7 @@ class MeasurementService extends PubSubService {
// For now, it is just added in OHIF here and in setMeasurementSelected.
this.measurements[internalUID] = newMeasurement;
if (isUpdate) {
this._broadcastEvent(this.EVENTS.MEASUREMENT_UPDATED, {
this._broadcastEvent(this.EVENTS.MEASUREMENT_UPDATED, {
source,
measurement: newMeasurement,
notYetUpdatedAtSource: false,

View File

@ -16,14 +16,13 @@ window.config = {
sourceName: 'dicomweb',
configuration: {
name: 'DCM4CHEE',
wadoUriRoot: 'http://localhost/dcm4chee-arc/aets/DCM4CHEE/wado',
qidoRoot: 'http://localhost/dcm4chee-arc/aets/DCM4CHEE/rs',
wadoRoot: 'http://localhost/dcm4chee-arc/aets/DCM4CHEE/rs',
wadoUriRoot: 'http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/wado',
qidoRoot: 'http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs',
wadoRoot: 'http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs',
qidoSupportsIncludeField: true,
imageRendering: 'wadors',
enableStudyLazyLoad: true,
thumbnailRendering: 'wadors',
useBulkDataURI: false,
requestOptions: {
auth: 'admin:admin',
},