fix: the start/end command in TMTV for the ROIStartEndThreshold tools (#4281)

This commit is contained in:
Celian-abd authored and GitHub committed 2024-07-09 14:49:42 -04:00
1 parent 4b91ce4df9
commit 38c19fab77
5 files changed
+137 -50

No files matched your search

+13 -32
View File
@@ -12,9 +12,10 @@ import dicomRTAnnotationExport from './utils/dicomRTAnnotationExport/RTStructure
import { getWebWorkerManager } from '@cornerstonejs/core';
const metadataProvider = classes.MetadataProvider;
const RECTANGLE_ROI_THRESHOLD_MANUAL_TOOL_IDS = [
const ROI_THRESHOLD_MANUAL_TOOL_IDS = [
'RectangleROIStartEndThreshold',
'RectangleROIThreshold',
'CircleROIStartEndThreshold'
];
const LABELMAP = csTools.Enums.SegmentationRepresentations.Labelmap;
@@ -204,7 +205,7 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }:
const { referencedVolumeId } = cs.cache.getVolume(segVolumeId);
const annotationUIDs = _getAnnotationsSelectedByToolNames(
RECTANGLE_ROI_THRESHOLD_MANUAL_TOOL_IDS
ROI_THRESHOLD_MANUAL_TOOL_IDS
);
if (annotationUIDs.length === 0) {
@@ -291,7 +292,7 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }:
const referencedVolume = cs.cache.getVolume(referencedVolumeId);
const annotationUIDs = _getAnnotationsSelectedByToolNames(
RECTANGLE_ROI_THRESHOLD_MANUAL_TOOL_IDS
ROI_THRESHOLD_MANUAL_TOOL_IDS
);
const annotations = annotationUIDs.map(annotationUID =>
@@ -469,38 +470,18 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }:
},
setStartSliceForROIThresholdTool: () => {
const { viewport } = _getActiveViewportsEnabledElement();
const { focalPoint, viewPlaneNormal } = viewport.getCamera();
const { focalPoint } = viewport.getCamera();
const selectedAnnotationUIDs = _getAnnotationsSelectedByToolNames(
RECTANGLE_ROI_THRESHOLD_MANUAL_TOOL_IDS
ROI_THRESHOLD_MANUAL_TOOL_IDS
);
const annotationUID = selectedAnnotationUIDs[0];
const annotation = csTools.annotation.state.getAnnotation(annotationUID);
const { handles } = annotation.data;
const { points } = handles;
// get the current slice Index
const sliceIndex = viewport.getCurrentImageIdIndex();
annotation.data.startSlice = sliceIndex;
// distance between camera focal point and each point on the rectangle
const newPoints = points.map(point => {
const distance = vec3.create();
vec3.subtract(distance, focalPoint, point);
// distance in the direction of the viewPlaneNormal
const distanceInViewPlane = vec3.dot(distance, viewPlaneNormal);
// new point is current point minus distanceInViewPlane
const newPoint = vec3.create();
vec3.scaleAndAdd(newPoint, point, viewPlaneNormal, distanceInViewPlane);
return newPoint;
//
});
handles.points = newPoints;
// set the current focalpoint
annotation.data.startCoordinate = focalPoint;
// IMPORTANT: invalidate the toolData for the cached stat to get updated
// and re-calculate the projection points
annotation.invalidated = true;
@@ -510,16 +491,16 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }:
const { viewport } = _getActiveViewportsEnabledElement();
const selectedAnnotationUIDs = _getAnnotationsSelectedByToolNames(
RECTANGLE_ROI_THRESHOLD_MANUAL_TOOL_IDS
ROI_THRESHOLD_MANUAL_TOOL_IDS
);
const annotationUID = selectedAnnotationUIDs[0];
const annotation = csTools.annotation.state.getAnnotation(annotationUID);
// get the current slice Index
const sliceIndex = viewport.getCurrentImageIdIndex();
annotation.data.endSlice = sliceIndex;
// get the current focalpoint
const focalPointToEnd = viewport.getCamera().focalPoint;
annotation.data.endCoordinate = focalPointToEnd;
// IMPORTANT: invalidate the toolData for the cached stat to get updated
// and re-calculate the projection points
@@ -535,7 +516,7 @@ const commandsModule = ({ servicesManager, commandsManager, extensionManager }:
Object.keys(stateManager.annotations).forEach(frameOfReferenceUID => {
const forAnnotations = stateManager.annotations[frameOfReferenceUID];
const ROIAnnotations = RECTANGLE_ROI_THRESHOLD_MANUAL_TOOL_IDS.reduce(
const ROIAnnotations = ROI_THRESHOLD_MANUAL_TOOL_IDS.reduce(
(annotations, toolName) => [...annotations, ...(forAnnotations[toolName] ?? [])],
[]
);
+11 -2
View File
@@ -1,4 +1,4 @@
import { addTool, RectangleROIStartEndThresholdTool } from '@cornerstonejs/tools';
import { addTool, RectangleROIStartEndThresholdTool, CircleROIStartEndThresholdTool } from '@cornerstonejs/tools';
import measurementServiceMappingsFactory from './utils/measurementServiceMappings/measurementServiceMappingsFactory';
@@ -15,8 +15,9 @@ export default function init({ servicesManager }) {
servicesManager.services;
addTool(RectangleROIStartEndThresholdTool);
addTool(CircleROIStartEndThresholdTool);
const { RectangleROIStartEndThreshold } = measurementServiceMappingsFactory(
const { RectangleROIStartEndThreshold, CircleROIStartEndThreshold } = measurementServiceMappingsFactory(
measurementService,
displaySetService,
cornerstoneViewportService
@@ -34,4 +35,12 @@ export default function init({ servicesManager }) {
RectangleROIStartEndThreshold.toAnnotation,
RectangleROIStartEndThreshold.toMeasurement
);
measurementService.addMapping(
csTools3DVer1MeasurementSource,
'CircleROIStartEndThreshold',
CircleROIStartEndThreshold.matchingCriteria,
CircleROIStartEndThreshold.toAnnotation,
CircleROIStartEndThreshold.toMeasurement
);
}
@@ -0,0 +1,67 @@
import SUPPORTED_TOOLS from './constants/supportedTools';
import getSOPInstanceAttributes from './utils/getSOPInstanceAttributes';
const CircleROIStartEndThreshold = {
toAnnotation: (measurement, definition) => { },
/**
* Maps cornerstone annotation event data to measurement service format.
*
* @param {Object} cornerstone Cornerstone event data
* @return {Measurement} Measurement instance
*/
toMeasurement: (csToolsEventDetail, displaySetService, cornerstoneViewportService) => {
const { annotation, viewportId } = csToolsEventDetail;
const { metadata, data, annotationUID } = annotation;
if (!metadata || !data) {
console.warn('Length tool: Missing metadata or data');
return null;
}
const { toolName, referencedImageId, FrameOfReferenceUID } = metadata;
const validToolType = SUPPORTED_TOOLS.includes(toolName);
if (!validToolType) {
throw new Error('Tool not supported');
}
const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(
referencedImageId,
cornerstoneViewportService,
viewportId
);
let displaySet;
if (SOPInstanceUID) {
displaySet = displaySetService.getDisplaySetForSOPInstanceUID(
SOPInstanceUID,
SeriesInstanceUID
);
} else {
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
}
const { cachedStats } = data;
return {
uid: annotationUID,
SOPInstanceUID,
FrameOfReferenceUID,
// points,
metadata,
referenceSeriesUID: SeriesInstanceUID,
referenceStudyUID: StudyInstanceUID,
toolName: metadata.toolName,
displaySetInstanceUID: displaySet.displaySetInstanceUID,
label: metadata.label,
// displayText: displayText,
data: data.cachedStats,
type: 'CircleROIStartEndThreshold',
// getReport,
};
},
};
export default CircleROIStartEndThreshold;
@@ -1,4 +1,5 @@
import RectangleROIStartEndThreshold from './RectangleROIStartEndThreshold';
import CircleROIStartEndThreshold from './CircleROIStartEndThreshold'
const measurementServiceMappingsFactory = (
measurementService,
@@ -20,6 +21,20 @@ const measurementServiceMappingsFactory = (
},
],
},
CircleROIStartEndThreshold: {
toAnnotation: CircleROIStartEndThreshold.toAnnotation,
toMeasurement: csToolsAnnotation =>
CircleROIStartEndThreshold.toMeasurement(
csToolsAnnotation,
displaySetService,
cornerstoneViewportService
),
matchingCriteria: [
{
valueType: measurementService.VALUE_TYPES.ROI_THRESHOLD_MANUAL,
},
],
},
};
};