Skip to content

Commit

Permalink
fix(stackviewport): swap image row and column pixel spacing
Browse files Browse the repository at this point in the history
This commit swaps image row and column pixel spacing of `StackViewport` in `RenderingEngine` while applying an epsilon comparison for float numbers comparison. It also adds Zoom tool to the `StackScrollToolMouseWheelTool_test.js` test script to scroll through stacks of images. Finally, it adjusts the test image data and updates the `yarn.lock` file to include codec-openjph 2.4.2 package.
  • Loading branch information
sedghi committed Apr 17, 2023
1 parent bf2fa6e commit 14374d5
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 15 deletions.
4 changes: 2 additions & 2 deletions packages/core/src/RenderingEngine/StackViewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1537,8 +1537,8 @@ class StackViewport extends Viewport implements IStackViewport {
const dataType = imageData.getPointData().getScalars().getDataType();

// using epsilon comparison for float numbers comparison.
const isSameXSpacing = isEqual(xSpacing, image.rowPixelSpacing);
const isSameYSpacing = isEqual(ySpacing, image.columnPixelSpacing);
const isSameXSpacing = isEqual(xSpacing, image.columnPixelSpacing);
const isSameYSpacing = isEqual(ySpacing, image.rowPixelSpacing);

// using spacing, size, and direction only for now
return (
Expand Down
135 changes: 134 additions & 1 deletion packages/tools/test/StackScrollToolMouseWheelTool_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as testUtils from '../../../utils/test/testUtils';

import * as volumeURI_100_100_10_1_1_1_0_scrolled from './groundTruth/volumeURI_100_100_10_1_1_1_0_scrolled.png';
import * as imageURI_64_64_0_20_1_1_0_scrolled from './groundTruth/imageURI_64_64_0_20_1_1_0_scrolled.png';
import * as imageURI_64_64_10_5_3_2_0 from './groundTruth/imageURI_64_64_10_5_3_2_0.png';

const {
cache,
Expand All @@ -18,7 +19,12 @@ const {
const { Events, ViewportType, InterpolationType } = Enums;

const { registerVolumeLoader } = volumeLoader;
const { StackScrollMouseWheelTool, ToolGroupManager } = csTools3d;
const {
StackScrollMouseWheelTool,
ZoomTool,
ToolGroupManager,
Enums: { MouseBindings },
} = csTools3d;

const {
fakeImageLoader,
Expand Down Expand Up @@ -65,14 +71,26 @@ describe('Cornerstone Tools Scroll Wheel: ', () => {
beforeEach(function () {
csTools3d.init();
csTools3d.addTool(StackScrollMouseWheelTool);
csTools3d.addTool(ZoomTool);

cache.purgeCache();
this.DOMElements = [];

this.stackToolGroup = ToolGroupManager.createToolGroup(toolGroupId);
this.stackToolGroup.addTool(StackScrollMouseWheelTool.toolName, {
debounceIfNotLoaded: false,
});
this.stackToolGroup.addTool(ZoomTool.toolName, {
debounceIfNotLoaded: false,
});
this.stackToolGroup.setToolActive(StackScrollMouseWheelTool.toolName);
this.stackToolGroup.setToolActive(ZoomTool.toolName, {
bindings: [
{
mouseButton: MouseBindings.Secondary, // Right Click
},
],
});

this.renderingEngine = new RenderingEngine(renderingEngineId);
imageLoader.registerImageLoader('fakeImageLoader', fakeImageLoader);
Expand Down Expand Up @@ -254,4 +272,119 @@ describe('Cornerstone Tools Scroll Wheel: ', () => {
done.fail(e);
}
});

it('Should successfully scroll through stack of images of non square spacing', function (done) {
const element = createViewport(
this.renderingEngine,
ViewportType.STACK,
256,
256
);
this.DOMElements.push(element);

const imageId1 = 'fakeImageLoader:imageURI_64_64_10_5_3_2_0';
const imageId2 = 'fakeImageLoader:imageURI_64_64_15_5_3_2_0';
const vp = this.renderingEngine.getViewport(viewportId);

let handlerRun = false;
function renderEventHandler() {
if (handlerRun) return;
handlerRun = true;

// First render is the actual image render
const index1 = [0, 0, 4];
const index2 = [10, 10, 4];

const { imageData } = vp.getImageData();

const {
pageX: pageX1,
pageY: pageY1,
clientX: clientX1,
clientY: clientY1,
} = createNormalizedMouseEvent(imageData, index1, element, vp);

const {
pageX: pageX2,
pageY: pageY2,
clientX: clientX2,
clientY: clientY2,
} = createNormalizedMouseEvent(imageData, index2, element, vp);

let evt = new MouseEvent('mousedown', {
target: element,
buttons: 2,
clientX: clientX1,
clientY: clientY1,
pageX: pageX1,
pageY: pageY1,
});
element.dispatchEvent(evt);

// Mouse move to put the end somewhere else
evt = new MouseEvent('mousemove', {
target: element,
buttons: 2,
clientX: clientX2,
clientY: clientY2,
pageX: pageX2,
pageY: pageY2,
});
document.dispatchEvent(evt);

setTimeout(() => {
evt = new WheelEvent('wheel', {
target: element,
pageX: pageX1,
pageY: pageY1,
deltaX: 0,
deltaY: 12,
deltaMode: 0,
wheelDelta: -36,
wheelDeltaX: 0,
wheelDeltaY: -36,
});

attachEventHandler();

element.removeEventListener(Events.IMAGE_RENDERED, renderEventHandler);
element.dispatchEvent(evt);
}, 500);
}

function attachEventHandler() {
const canvas = vp.getCanvas();

element.addEventListener(
Events.IMAGE_RENDERED,
function secondImageRendered() {
// Second render is as a result of scrolling
const image = canvas.toDataURL('image/png');
element.removeEventListener(
Events.IMAGE_RENDERED,
secondImageRendered
);

compareImages(
image,
imageURI_64_64_10_5_3_2_0,
'imageURI_64_64_10_5_3_2_0'
).then(done, done.fail);
}
);
}

element.addEventListener(Events.IMAGE_RENDERED, renderEventHandler);

this.stackToolGroup.addViewport(vp.id, this.renderingEngine.id);

try {
vp.setStack([imageId1, imageId2], 0).then(() => {
vp.setProperties({ interpolationType: InterpolationType.NEAREST });
vp.render();
});
} catch (e) {
done.fail(e);
}
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions utils/test/testUtilsImageLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ const fakeImageLoader = (imageId) => {
windowWidth: 400,
maxPixelValue: 255,
minPixelValue: 0,
rowPixelSpacing: 1,
columnPixelSpacing: 1,
rowPixelSpacing: y_spacing,
columnPixelSpacing: x_spacing,
getPixelData: () => pixelData,
sizeInBytes: rows * columns * 1, // 1 byte for now
FrameOfReferenceUID: 'Stack_Frame_Of_Reference',
Expand Down Expand Up @@ -124,8 +124,8 @@ function fakeMetaDataProvider(type, imageId) {
columnCosines: [0, 1, 0],
imagePositionPatient: [0, 0, 0],
pixelSpacing: [x_spacing, y_spacing],
rowPixelSpacing: x_spacing,
columnPixelSpacing: y_spacing,
rowPixelSpacing: y_spacing,
columnPixelSpacing: x_spacing,
};

return imagePlaneModule;
Expand Down
8 changes: 0 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2539,14 +2539,6 @@
resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.2.tgz#e96721d56f6ec96f7f95c16321d88cc8467d8d81"
integrity sha512-lgdvBvvNezleY+4pIe2ceUsJzlZe/0PipdeubQ3vZZOz3xxtHHMR1XFCl4fgd8gosR8COHuD7h6q+MwgrwBsng==

"@cornerstonejs/core@^0.31.0":
version "0.31.2"
resolved "https://registry.npmjs.org/@cornerstonejs/core/-/core-0.31.2.tgz#0087cb4445962c82125ae2dddff49aadcfab634d"
integrity sha512-RIxKF/3gGvx8Rca91YlAkUF0DVICedHr6Xis9x8EvOIm+DraP1h3FSQs6bO77FdalAEPGyDjG5U8ZfsAkAXN4g==
dependencies:
detect-gpu "^4.0.45"
lodash.clonedeep "4.5.0"

"@cspotcode/source-map-consumer@0.8.0":
version "0.8.0"
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b"
Expand Down

0 comments on commit 14374d5

Please sign in to comment.