Skip to content

Commit

Permalink
Merge pull request #1442 from wayfarer3130/fix/cobbAngleRestoreFix
Browse files Browse the repository at this point in the history
Fix some publish/create SR using dcmjs
  • Loading branch information
igoroctaviano authored Oct 25, 2021
2 parents 1bd6e17 + e7a9095 commit f518bd8
Show file tree
Hide file tree
Showing 8 changed files with 296 additions and 18 deletions.
3 changes: 3 additions & 0 deletions src/__mocks__/externalModules.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import cornerstoneMath from 'cornerstone-math';

export default {
cornerstone: {
getEnabledElement: jest.fn().mockImplementation(() => ({
Expand All @@ -19,6 +21,7 @@ export default {
updateImage: jest.fn(),
},
cornerstoneMath: {
...cornerstoneMath,
point: {
distance: jest.fn(),
},
Expand Down
48 changes: 32 additions & 16 deletions src/tools/annotation/CobbAngleTool.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,14 @@ export default class CobbAngleTool extends BaseAnnotationTool {
return false;
}

return (
const seg1Near =
lineSegDistance(element, data.handles.start, data.handles.end, coords) <
25 ||
25;
const seg2Near =
lineSegDistance(element, data.handles.start2, data.handles.end2, coords) <
25
);
25;

return seg1Near || seg2Near;
}

updateCachedStats(image, element, data) {
Expand Down Expand Up @@ -182,6 +184,9 @@ export default class CobbAngleTool extends BaseAnnotationTool {
const lineWidth = toolStyle.getToolWidth();
const lineDash = getModule('globalConfiguration').configuration.lineDash;
const font = textStyle.getFont();
const { element } = evt.detail;
const image = external.cornerstone.getEnabledElement(element).image;
const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image);

for (let i = 0; i < toolData.data.length; i++) {
const data = toolData.data[i];
Expand All @@ -190,6 +195,10 @@ export default class CobbAngleTool extends BaseAnnotationTool {
continue;
}

if (!data.value) {
data.value = this.textBoxText(data, rowPixelSpacing, colPixelSpacing);
}

draw(context, context => {
setShadow(context, this.configuration);

Expand Down Expand Up @@ -291,6 +300,15 @@ export default class CobbAngleTool extends BaseAnnotationTool {

return;
}
const eventType = EVENTS.MEASUREMENT_COMPLETED;
const eventData = {
toolName: this.name,
toolType: this.name, // Deprecation notice: toolType will be replaced by toolName
element,
measurementData,
};

triggerEvent(element, eventType, eventData);
};

// Search for incomplete measurements
Expand Down Expand Up @@ -373,22 +391,20 @@ export default class CobbAngleTool extends BaseAnnotationTool {
}
}

const { rAngle } = data;

data.value = '';
data.value = this.textBoxText(data, rowPixelSpacing, colPixelSpacing);
}

if (!Number.isNaN(rAngle)) {
data.value = textBoxText(rAngle, rowPixelSpacing, colPixelSpacing);
textBoxText({ rAngle }, rowPixelSpacing, colPixelSpacing) {
if (rAngle === undefined) {
return '';
}
if (Number.isNaN(rAngle)) {
return '';
}

function textBoxText(rAngle, rowPixelSpacing, colPixelSpacing) {
const suffix = !rowPixelSpacing || !colPixelSpacing ? ' (isotropic)' : '';
const str = '00B0'; // Degrees symbol
const suffix = !rowPixelSpacing || !colPixelSpacing ? ' (isotropic)' : '';

return (
rAngle.toString() + String.fromCharCode(parseInt(str, 16)) + suffix
);
}
return `${rAngle}\u00B0${suffix}`;
}

activeCallback(element) {
Expand Down
237 changes: 237 additions & 0 deletions src/tools/annotation/CobbAngleTool.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
import Tool from './CobbAngleTool.js';
import { getToolState } from '../../stateManagement/toolState.js';

jest.mock('./../../stateManagement/toolState.js', () => ({
getToolState: jest.fn(),
}));

jest.mock('./../../externalModules.js');
import external from '../../externalModules.js';

const goodMouseEventData = {
currentPoints: {
image: {
x: 0,
y: 0,
},
},
};

const image = {
rowPixelSpacing: 0.8984375,
columnPixelSpacing: 0.8984375,
};

describe('CobbAngleTool.js', () => {
beforeEach(() => {
jest.resetAllMocks();
});

describe('default values', () => {
it('has a default name of "CobbAngle"', () => {
const defaultName = 'CobbAngle';
const instantiatedTool = new Tool();

expect(instantiatedTool.name).toEqual(defaultName);
});

it('can be created with a custom tool name', () => {
const customToolName = { name: 'customToolName' };
const instantiatedTool = new Tool(customToolName);

expect(instantiatedTool.name).toEqual(customToolName.name);
});
});

describe('createNewMeasurement', () => {
it('returns aa new measurement object', () => {
const instantiatedTool = new Tool('CobbAngle');

const toolMeasurement = instantiatedTool.createNewMeasurement(
goodMouseEventData
);

expect(typeof toolMeasurement).toBe(typeof {});
});

it("returns a measurement with a start, end, start2 and end2 handles at the eventData's x and y", () => {
const instantiatedTool = new Tool('toolName');

const toolMeasurement = instantiatedTool.createNewMeasurement(
goodMouseEventData
);
const startHandle = {
x: toolMeasurement.handles.start.x,
y: toolMeasurement.handles.start.y,
};
const endHandle = {
x: toolMeasurement.handles.end.x,
y: toolMeasurement.handles.end.y,
};
const start2Handle = {
x: toolMeasurement.handles.start2.x,
y: toolMeasurement.handles.start2.y,
};
const end2Handle = {
x: toolMeasurement.handles.end2.x,
y: toolMeasurement.handles.end2.y,
};

expect(startHandle.x).toBe(goodMouseEventData.currentPoints.image.x);
expect(startHandle.y).toBe(goodMouseEventData.currentPoints.image.y);
expect(start2Handle.x).toBe(goodMouseEventData.currentPoints.image.x);
expect(start2Handle.y).toBe(goodMouseEventData.currentPoints.image.y);
expect(endHandle.x).toBe(goodMouseEventData.currentPoints.image.x);
expect(endHandle.y).toBe(goodMouseEventData.currentPoints.image.y);
expect(end2Handle.x).toBe(goodMouseEventData.currentPoints.image.x + 1);
expect(end2Handle.y).toBe(goodMouseEventData.currentPoints.image.y);
});

it('returns a measurement with a textBox handle', () => {
const instantiatedTool = new Tool('toolName');

const toolMeasurement = instantiatedTool.createNewMeasurement(
goodMouseEventData
);

expect(typeof toolMeasurement.handles.textBox).toBe(typeof {});
});
});

describe('pointNearTool', () => {
let element, coords;

beforeEach(() => {
element = jest.fn();
coords = jest.fn();
});

it('returns false when measurement data is not visible', () => {
const instantiatedTool = new Tool('AngleTool');
const notVisibleMeasurementData = {
visible: false,
};

const isPointNearTool = instantiatedTool.pointNearTool(
element,
notVisibleMeasurementData,
coords
);

expect(isPointNearTool).toBe(false);
});

it('returns false when measurement data is incomplete', () => {
const instantiatedTool = new Tool('AngleTool');
instantiatedTool.hasIncomplete = true;
const measurementData = {
visible: true,
handles: {
start: { x: 10, y: 10 },
end: { x: 20, y: 10 },
},
};
const isPointNearTool = instantiatedTool.pointNearTool(
element,
measurementData,
measurementData.handles.start
);

expect(isPointNearTool).toBe(false);
});

it('returns true when measurement data is near the end points', () => {
const instantiatedTool = new Tool('AngleTool');
const measurementData = {
visible: true,
handles: {
start: { x: 10, y: 10 },
end: { x: 20, y: 10 },
start2: { x: 40, y: 10 },
end2: { x: 40, y: 40 },
},
};

external.cornerstone.pixelToCanvas.mockImplementation((el, pt) => {
return pt;
});

expect(
instantiatedTool.pointNearTool(element, measurementData, {
x: 70,
y: 10,
})
).toBe(false);

expect(
instantiatedTool.pointNearTool(
element,
measurementData,
measurementData.handles.start
)
).toBe(true);

expect(
instantiatedTool.pointNearTool(
element,
measurementData,
measurementData.handles.end2
)
).toBe(true);
});
});

describe('updateCachedStats', () => {
let element;

beforeEach(() => {
element = jest.fn();
});

it('should calculate and update annotation value', () => {
const instantiatedTool = new Tool('AngleTool');

const data = {
handles: {
start: {
x: 166,
y: 90,
},
end: {
x: 120,
y: 113,
},
start2: {
x: 120,
y: 113,
},
end2: {
x: 145,
y: 143,
},
},
};

instantiatedTool.updateCachedStats(image, element, data);
expect(data.rAngle).toBe(76.76);
expect(data.invalidated).toBe(false);
});
});

describe('renderToolData', () => {
it('returns undefined when no toolData exists for the tool', () => {
const instantiatedTool = new Tool('AngleTool');
const mockEvent = {
detail: {
enabledElement: undefined,
},
};

getToolState.mockReturnValueOnce(undefined);

const renderResult = instantiatedTool.renderToolData(mockEvent);

expect(renderResult).toBe(undefined);
});
});
});
2 changes: 1 addition & 1 deletion src/tools/annotation/ProbeTool.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ export default class ProbeTool extends BaseAnnotationTool {

if (this.configuration.drawHandles) {
// Draw the handles
let handleOptions = { handleRadius, color };
const handleOptions = { handleRadius, color };

if (renderDashed) {
handleOptions.lineDash = lineDash;
Expand Down
5 changes: 5 additions & 0 deletions src/tools/annotation/RectangleRoiTool.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,13 @@ function _calculateStats(image, element, handles, modality, pixelSpacing) {
(pixelSpacing.colPixelSpacing || 1) *
(roiCoordinates.height * (pixelSpacing.rowPixelSpacing || 1));

const perimeter =
roiCoordinates.width * 2 * (pixelSpacing.colPixelSpacing || 1) +
roiCoordinates.height * 2 * (pixelSpacing.rowPixelSpacing || 1);

return {
area: area || 0,
perimeter,
count: roiMeanStdDev.count || 0,
mean: roiMeanStdDev.mean || 0,
variance: roiMeanStdDev.variance || 0,
Expand Down
1 change: 1 addition & 0 deletions src/tools/annotation/RectangleRoiTool.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ describe('RectangleRoiTool.js', () => {

instantiatedTool.updateCachedStats(image, element, data);
expect(data.cachedStats.area.toFixed(2)).toEqual('7.26');
expect(data.cachedStats.perimeter.toFixed(2)).toEqual('10.78');
expect(data.cachedStats.mean.toFixed(2)).toEqual('57.56');
expect(data.cachedStats.stdDev.toFixed(2)).toEqual('47.46');

Expand Down
1 change: 1 addition & 0 deletions src/util/convertToVector3.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import external from '../externalModules.js';

jest.mock('../externalModules.js', () => {
const cornerstoneMath = require('cornerstone-math');

return {
cornerstoneMath: {
Vector3: cornerstoneMath.Vector3,
Expand Down
Loading

0 comments on commit f518bd8

Please sign in to comment.