fix(measurements): Update the calibration tool to match changes in CS3D (#3505)

This change makes the OHIF side consistent with the CS3D user calibration settings, and will correctly display px and rounding values consistent with the CS3D display.
This commit is contained in:
Bill Wallace authored and GitHub committed 2023-09-15 10:50:23 -04:00
1 parent bd7f9592ea
commit 38af3112ec
8 files changed
+177 -90

No files matched your search

@@ -76,11 +76,12 @@ export function onCompletedCalibrationLine(servicesManager, csToolsEvent) {
const adjustCalibration = newLength => {
const spacingScale = newLength / length;
const rowSpacing = spacingScale * currentRowPixelSpacing;
const colSpacing = spacingScale * currentColumnPixelSpacing;
// trigger resize of the viewport to adjust the world/pixel mapping
calibrateImageSpacing(imageId, viewport.getRenderingEngine(), rowSpacing, colSpacing);
calibrateImageSpacing(imageId, viewport.getRenderingEngine(), {
type: 'User',
scale: 1 / spacingScale,
});
};
return new Promise((resolve, reject) => {
@@ -99,8 +99,7 @@ function getMappedAnnotations(annotation, displaySetService) {
);
const { SeriesNumber } = displaySet;
const { length, width } = targetStats;
const unit = 'mm';
const { length, width, unit } = targetStats;
annotations.push({
SeriesInstanceUID,
@@ -130,9 +129,9 @@ function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
values.push('Cornerstone:Bidirectional');
mappedAnnotations.forEach(annotation => {
const { length, width } = annotation;
columns.push(`Length (mm)`, `Width (mm)`);
values.push(length, width);
const { length, width, unit } = annotation;
columns.push(`Length`, `Width`, 'Unit');
values.push(length, width, unit);
});
if (FrameOfReferenceUID) {
@@ -162,7 +161,14 @@ function getDisplayText(mappedAnnotations, displaySet) {
const displayText = [];
// Area is the same for all series
const { length, width, SeriesNumber, SOPInstanceUID, frameNumber } = mappedAnnotations[0];
const {
length,
width,
unit,
SeriesNumber,
SOPInstanceUID,
frameNumber,
} = mappedAnnotations[0];
const roundedLength = utils.roundNumber(length, 2);
const roundedWidth = utils.roundNumber(width, 2);
@@ -176,8 +182,10 @@ function getDisplayText(mappedAnnotations, displaySet) {
const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';
const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';
displayText.push(`L: ${roundedLength} mm (S: ${SeriesNumber}${instanceText}${frameText})`);
displayText.push(`W: ${roundedWidth} mm`);
displayText.push(
`L: ${roundedLength} ${unit} (S: ${SeriesNumber}${instanceText}${frameText})`
);
displayText.push(`W: ${roundedWidth} ${unit}`);
return displayText;
}
@@ -98,7 +98,7 @@ function getMappedAnnotations(annotation, DisplaySetService) {
);
const { SeriesNumber } = displaySet;
const { mean, stdDev, max, area, Modality, modalityUnit } = targetStats;
const { mean, stdDev, max, area, Modality, areaUnit, modalityUnit } = targetStats;
annotations.push({
SeriesInstanceUID,
@@ -111,6 +111,7 @@ function getMappedAnnotations(annotation, DisplaySetService) {
stdDev,
max,
area,
areaUnit,
});
});
@@ -131,14 +132,20 @@ function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
values.push('Cornerstone:CircleROI');
mappedAnnotations.forEach(annotation => {
const { mean, stdDev, max, area, unit } = annotation;
const { mean, stdDev, max, area, unit, areaUnit } = annotation;
if (!mean || !unit || !max || !area) {
return;
}
columns.push(`max (${unit})`, `mean (${unit})`, `std (${unit})`, `area (mm2)`);
values.push(max, mean, stdDev, area);
columns.push(
`max (${unit})`,
`mean (${unit})`,
`std (${unit})`,
'Area',
'Unit'
);
values.push(max, mean, stdDev, area, areaUnit);
});
if (FrameOfReferenceUID) {
@@ -168,7 +175,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
const displayText = [];
// Area is the same for all series
const { area, SOPInstanceUID, frameNumber } = mappedAnnotations[0];
const { area, SOPInstanceUID, frameNumber, areaUnit } = mappedAnnotations[0];
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
@@ -182,7 +189,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
// Area sometimes becomes undefined if `preventHandleOutsideImage` is off.
const roundedArea = utils.roundNumber(area || 0, 2);
displayText.push(`${roundedArea} mm<sup>2</sup>`);
displayText.push(`${roundedArea} ${areaUnit}`);
// Todo: we need a better UI for displaying all these information
mappedAnnotations.forEach(mappedAnnotation => {
@@ -98,7 +98,7 @@ function getMappedAnnotations(annotation, displaySetService) {
);
const { SeriesNumber } = displaySet;
const { mean, stdDev, max, area, Modality, modalityUnit } = targetStats;
const { mean, stdDev, max, area, Modality, areaUnit, modalityUnit } = targetStats;
annotations.push({
SeriesInstanceUID,
@@ -107,6 +107,7 @@ function getMappedAnnotations(annotation, displaySetService) {
frameNumber,
Modality,
unit: modalityUnit,
areaUnit,
mean,
stdDev,
max,
@@ -131,14 +132,20 @@ function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
values.push('Cornerstone:EllipticalROI');
mappedAnnotations.forEach(annotation => {
const { mean, stdDev, max, area, unit } = annotation;
const { mean, stdDev, max, area, unit, areaUnit } = annotation;
if (!mean || !unit || !max || !area) {
return;
}
columns.push(`max (${unit})`, `mean (${unit})`, `std (${unit})`, `area (mm2)`);
values.push(max, mean, stdDev, area);
columns.push(
`max (${unit})`,
`mean (${unit})`,
`std (${unit})`,
'Area',
'Unit'
);
values.push(max, mean, stdDev, area, areaUnit);
});
if (FrameOfReferenceUID) {
@@ -168,7 +175,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
const displayText = [];
// Area is the same for all series
const { area, SOPInstanceUID, frameNumber } = mappedAnnotations[0];
const { area, SOPInstanceUID, frameNumber, areaUnit } = mappedAnnotations[0];
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
@@ -180,9 +187,8 @@ function getDisplayText(mappedAnnotations, displaySet) {
const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';
const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';
// Area sometimes becomes undefined if `preventHandleOutsideImage` is off.
const roundedArea = utils.roundNumber(area || 0, 2);
displayText.push(`${roundedArea} mm<sup>2</sup>`);
const roundedArea = utils.roundNumber(area, 2);
displayText.push(`${roundedArea} ${areaUnit}`);
// Todo: we need a better UI for displaying all these information
mappedAnnotations.forEach(mappedAnnotation => {
@@ -32,7 +32,11 @@ const Length = {
throw new Error('Tool not supported');
}
const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(
const {
SOPInstanceUID,
SeriesInstanceUID,
StudyInstanceUID,
} = getSOPInstanceAttributes(
referencedImageId,
cornerstoneViewportService,
viewportId
@@ -94,8 +98,11 @@ function getMappedAnnotations(annotation, displaySetService) {
throw new Error('Non-acquisition plane measurement mapping not supported');
}
const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =
getSOPInstanceAttributes(referencedImageId);
const {
SOPInstanceUID,
SeriesInstanceUID,
frameNumber,
} = getSOPInstanceAttributes(referencedImageId);
const displaySet = displaySetService.getDisplaySetForSOPInstanceUID(
SOPInstanceUID,
@@ -104,8 +111,7 @@ function getMappedAnnotations(annotation, displaySetService) {
);
const { SeriesNumber } = displaySet;
const { length } = targetStats;
const unit = 'mm';
const { length, unit = 'mm' } = targetStats;
annotations.push({
SeriesInstanceUID,
@@ -134,9 +140,11 @@ function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
values.push('Cornerstone:Length');
mappedAnnotations.forEach(annotation => {
const { length } = annotation;
columns.push(`Length (mm)`);
const { length, unit } = annotation;
columns.push(`Length`);
values.push(length);
columns.push('Unit');
values.push(unit);
});
if (FrameOfReferenceUID) {
@@ -166,7 +174,13 @@ function getDisplayText(mappedAnnotations, displaySet) {
const displayText = [];
// Area is the same for all series
const { length, SeriesNumber, SOPInstanceUID, frameNumber } = mappedAnnotations[0];
const {
length,
SeriesNumber,
SOPInstanceUID,
frameNumber,
unit,
} = mappedAnnotations[0];
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
@@ -182,7 +196,9 @@ function getDisplayText(mappedAnnotations, displaySet) {
return displayText;
}
const roundedLength = utils.roundNumber(length, 2);
displayText.push(`${roundedLength} mm (S: ${SeriesNumber}${instanceText}${frameText})`);
displayText.push(
`${roundedLength} ${unit} (S: ${SeriesNumber}${instanceText}${frameText})`
);
return displayText;
}
@@ -25,7 +25,11 @@ const RectangleROI = {
throw new Error('Tool not supported');
}
const { SOPInstanceUID, SeriesInstanceUID, StudyInstanceUID } = getSOPInstanceAttributes(
const {
SOPInstanceUID,
SeriesInstanceUID,
StudyInstanceUID,
} = getSOPInstanceAttributes(
referencedImageId,
CornerstoneViewportService,
viewportId
@@ -88,8 +92,11 @@ function getMappedAnnotations(annotation, DisplaySetService) {
throw new Error('Non-acquisition plane measurement mapping not supported');
}
const { SOPInstanceUID, SeriesInstanceUID, frameNumber } =
getSOPInstanceAttributes(referencedImageId);
const {
SOPInstanceUID,
SeriesInstanceUID,
frameNumber,
} = getSOPInstanceAttributes(referencedImageId);
const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(
SOPInstanceUID,
@@ -98,7 +105,7 @@ function getMappedAnnotations(annotation, DisplaySetService) {
);
const { SeriesNumber } = displaySet;
const { mean, stdDev, max, area, Modality, modalityUnit } = targetStats;
const { mean, stdDev, max, area, Modality, modalityUnit, areaUnit } = targetStats;
annotations.push({
SeriesInstanceUID,
@@ -111,6 +118,7 @@ function getMappedAnnotations(annotation, DisplaySetService) {
stdDev,
max,
area,
areaUnit,
});
});
@@ -131,14 +139,14 @@ function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
values.push('Cornerstone:RectangleROI');
mappedAnnotations.forEach(annotation => {
const { mean, stdDev, max, area, unit } = annotation;
const { mean, stdDev, max, area, unit, areaUnit } = annotation;
if (!mean || !unit || !max || !area) {
return;
}
columns.push(`max (${unit})`, `mean (${unit})`, `std (${unit})`, `area (mm2)`);
values.push(max, mean, stdDev, area);
columns.push(`Maximum`, `Mean`, `Std Dev`, 'Pixel Unit', `Area`, 'Unit');
values.push(max, mean, stdDev, unit, area, areaUnit);
});
if (FrameOfReferenceUID) {
@@ -168,7 +176,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
const displayText = [];
// Area is the same for all series
const { area, SOPInstanceUID, frameNumber } = mappedAnnotations[0];
const { area, SOPInstanceUID, frameNumber, areaUnit } = mappedAnnotations[0];
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
@@ -182,7 +190,7 @@ function getDisplayText(mappedAnnotations, displaySet) {
// Area sometimes becomes undefined if `preventHandleOutsideImage` is off.
const roundedArea = utils.roundNumber(area || 0, 2);
displayText.push(`${roundedArea} mm<sup>2</sup>`);
displayText.push(`${roundedArea} ${areaUnit}`);
// Todo: we need a better UI for displaying all these information
mappedAnnotations.forEach(mappedAnnotation => {