Skip to content

Commit

Permalink
fix(cornerstoneTools):Add a center circle display as an option (#1476)
Browse files Browse the repository at this point in the history
* fix(cornerstoneTools):Add a center circle display as an option

* feat(cornerstoneTools):Add a circle ROI with radius and options center

* Added unit tests for the new circle functionality
  • Loading branch information
wayfarer3130 authored May 13, 2022
1 parent 4a95420 commit ec5240e
Show file tree
Hide file tree
Showing 11 changed files with 31,277 additions and 610 deletions.
31,679 changes: 31,099 additions & 580 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"all-contributors-cli": "5.11.0",
"babel-jest": "^25.1.0",
"babel-loader": "^8.0.4",
"canvas": "2.6.1",
"canvas": "^2.9.1",
"commitizen": "^4.0.3",
"coveralls": "3.0.2",
"cz-conventional-changelog": "2.1.0",
Expand Down
2 changes: 1 addition & 1 deletion src/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default function(defaultConfiguration = {}) {
}
});
} else {
// defaultConfiguration is an object, default to assigning it to globalConfiguration.
// DefaultConfiguration is an object, default to assigning it to globalConfiguration.
globalConfigurationModule.configuration = Object.assign(
{},
globalConfigurationModule.configuration,
Expand Down
1 change: 1 addition & 0 deletions src/stackTools/stackPrefetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ function nearestIndex(arr, x) {
// http://stackoverflow.com/questions/25854212/return-index-of-nearest-values-in-an-array
let low = 0;
let high = arr.length - 1;

arr.forEach((v, idx) => {
if (v < x) {
low = Math.max(idx, low);
Expand Down
2 changes: 1 addition & 1 deletion src/stateManagement/imageIdSpecificStateManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ function newImageIdSpecificToolStateManager() {
function setImageIdToolState(imageId, toolName, data) {
const imageIdToolState = toolState[imageId];

// set the toolState
// Set the toolState
imageIdToolState[toolName] = data;
}

Expand Down
5 changes: 3 additions & 2 deletions src/store/modules/manipulatorStateModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ function removeActiveManipulatorForElement(element) {
function cancelActiveManipulatorsForElement(element) {
const enabledElement = external.cornerstone.getEnabledElement(element);
const enabledElementUUID = enabledElement.uuid;

_cancelActiveManipulatorsForElementUUID(enabledElementUUID);
}

Expand Down Expand Up @@ -65,11 +66,11 @@ function enabledElementCallback(element) {

export default {
setters: {
// add/remove
// Add/remove
addActiveManipulatorForElement,
removeActiveManipulatorForElement,

// cancel
// Cancel
cancelActiveManipulatorsForElement,
cancelActiveManipulators,
},
Expand Down
13 changes: 10 additions & 3 deletions src/tools/OverlayTool.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ export default class OverlayTool extends BaseTool {
}

setupRender(image) {
if (!image) return;
if (!image) {
return;
}
const overlayPlaneMetadata = external.cornerstone.metaData.get(
'overlayPlaneModule',
image.imageId
Expand All @@ -69,7 +71,10 @@ export default class OverlayTool extends BaseTool {
globalConfiguration.configuration.overlayColor || 'white';
}
// Allow turning off overlays by setting overlayColor to false
if (viewport.overlayColor === false) return;
if (viewport.overlayColor === false) {
return;
}

return true;
}

Expand All @@ -81,7 +86,9 @@ export default class OverlayTool extends BaseTool {
if (!eventData || !enabledElement || !overlayPlaneMetadata) {
return;
}
if (!this.setupViewport(viewport)) return;
if (!this.setupViewport(viewport)) {
return;
}

const imageWidth = image.columns;
const imageHeight = image.rows;
Expand Down
1 change: 1 addition & 0 deletions src/tools/annotation/ArrowAnnotateTool.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ export default class ArrowAnnotateTool extends BaseAnnotationTool {
const lineWidth = toolStyle.getToolWidth();

let lineDash;

if (renderDashed) {
lineDash = getModule('globalConfiguration').configuration.lineDash;
}
Expand Down
59 changes: 56 additions & 3 deletions src/tools/annotation/CircleRoiTool.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default class CircleRoiTool extends BaseAnnotationTool {
supportedInteractionTypes: ['Mouse', 'Touch'],
svgCursor: circleRoiCursor,
configuration: {
centerPointRadius: 0,
renderDashed: false,
hideHandlesIfMoving: false,
},
Expand Down Expand Up @@ -174,6 +175,7 @@ export default class CircleRoiTool extends BaseAnnotationTool {
drawHandlesOnHover,
hideHandlesIfMoving,
renderDashed,
centerPointRadius,
} = this.configuration;
const newContext = getNewContext(canvasContext.canvas);
const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image);
Expand Down Expand Up @@ -237,6 +239,22 @@ export default class CircleRoiTool extends BaseAnnotationTool {
'pixel'
);

if (centerPointRadius && radius > 3 * centerPointRadius) {
drawCircle(
context,
element,
data.handles.start,
centerPointRadius,
circleOptions,
'pixel'
);
}

if (data.handles) {
data.handles.start.drawnIndependently = true;
data.handles.end.drawnIndependently = true;
}

drawHandles(context, eventData, data.handles, handleOptions);

// Update textbox stats
Expand Down Expand Up @@ -341,7 +359,16 @@ function _getUnit(modality, showHounsfieldUnits) {
function _createTextBoxContent(
context,
isColorImage,
{ area, mean, stdDev, min, max, meanStdDevSUV } = {},
{
area = 0,
radius = 0,
perimeter = 0,
mean = 0,
stdDev = 0,
min = 0,
max = 0,
meanStdDevSUV = 0,
} = {},
modality,
hasPixelSpacing,
options = {}
Expand Down Expand Up @@ -402,6 +429,12 @@ function _createTextBoxContent(
}

textLines.push(_formatArea(area, hasPixelSpacing));
if (radius) {
textLines.push(_formatLength(radius, 'Radius', hasPixelSpacing));
}
if (perimeter) {
textLines.push(_formatLength(perimeter, 'Perimeter', hasPixelSpacing));
}
otherLines.forEach(x => textLines.push(x));

return textLines;
Expand All @@ -423,6 +456,15 @@ function _formatArea(area, hasPixelSpacing) {
return `Area: ${numbersWithCommas(area.toFixed(2))}${suffix}`;
}

function _formatLength(value, name, hasPixelSpacing) {
if (!value) {
return '';
}
const suffix = hasPixelSpacing ? ' mm' : ' px';

return `${name}: ${numbersWithCommas(value.toFixed(1))}${suffix}`;
}

/**
*
*
Expand Down Expand Up @@ -461,13 +503,24 @@ function _calculateStats(image, element, handles, modality, pixelSpacing) {
};
}

const radius =
(circleCoordinates.width *
((pixelSpacing && pixelSpacing.colPixelSpacing) || 1)) /
2;
const perimeter = 2 * Math.PI * radius;
const area =
Math.PI *
((circleCoordinates.width * (pixelSpacing.colPixelSpacing || 1)) / 2) *
((circleCoordinates.height * (pixelSpacing.rowPixelSpacing || 1)) / 2);
((circleCoordinates.width *
((pixelSpacing && pixelSpacing.colPixelSpacing) || 1)) /
2) *
((circleCoordinates.height *
((pixelSpacing && pixelSpacing.rowPixelSpacing) || 1)) /
2);

return {
area: area || 0,
radius: radius || 0,
perimeter: perimeter || 0,
count: ellipseMeanStdDev.count || 0,
mean: ellipseMeanStdDev.mean || 0,
variance: ellipseMeanStdDev.variance || 0,
Expand Down
Loading

0 comments on commit ec5240e

Please sign in to comment.