Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions packages/tools/src/tools/annotation/ProbeTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,10 @@ class ProbeTool extends AnnotationTool {
if (csUtils.indexWithinDimensions(ijk, dimensions)) {
this.isHandleOutsideImage = false;

// Read voxel values with the image-space index: a stack's voxelManager
// holds a single image, so the overwritten ijk[2] below is out of range.
const voxelIJK: Types.Point3 = [ijk[0], ijk[1], ijk[2]];

// Index[2] for stackViewport is always 0, but for visualization
// we reset it to be imageId index (skip for ECG; channel is already in ijk[2])
if (targetId.startsWith('imageId:') && modality !== 'ECG') {
Expand All @@ -705,7 +709,7 @@ class ProbeTool extends AnnotationTool {
value = calibratedResults.values;
modalityUnit = calibratedResults.units;
} else if (modality === 'US') {
value = voxelManager?.getAtIJKPoint(ijk);
value = voxelManager?.getAtIJKPoint(voxelIJK);
const calibratedResults = getCalibratedProbeUnitsAndValue(image, [
ijk,
]);
Expand All @@ -719,7 +723,7 @@ class ProbeTool extends AnnotationTool {
? calibratedResults.units
: 'raw';
} else {
value = voxelManager?.getAtIJKPoint(ijk);
value = voxelManager?.getAtIJKPoint(voxelIJK);
modalityUnit = getPixelValueUnits(
modality,
annotation.metadata.referencedImageId,
Expand Down
86 changes: 86 additions & 0 deletions packages/tools/test/ProbeTool_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,92 @@ describe('Probe Tool:', () => {
}
});

it('Should read the probe value on a stack image other than the first one', function (done) {
const element = createViewports(renderingEngine, {
viewportType: ViewportType.STACK,
width: 512,
height: 128,
viewportId: viewportId,
});

const imageInfo = {
loader: 'fakeImageLoader',
name: 'imageURI',
rows: 64,
columns: 64,
barStart: 10,
barWidth: 5,
xSpacing: 1,
ySpacing: 1,
};

const imageId0 = encodeImageIdInfo({ ...imageInfo, sliceIndex: 0 });
const imageId1 = encodeImageIdInfo({ ...imageInfo, sliceIndex: 1 });
const vp = renderingEngine.getViewport(viewportId);

const addEventListenerForAnnotationRendered = () => {
element.addEventListener(csToolsEvents.ANNOTATION_RENDERED, () => {
const probeAnnotations = annotation.state.getAnnotations(
ProbeTool.toolName,
element
);
expect(probeAnnotations.length).toBe(1);

const probeAnnotation = probeAnnotations[0];
expect(probeAnnotation.metadata.referencedImageId).toBe(imageId1);

const data = probeAnnotation.data.cachedStats;
const targets = Array.from(Object.keys(data));
expect(targets.length).toBe(1);

// The world coordinate is on the white bar of the second image
expect(data[targets[0]].value).toBe(255);
// The displayed index still reports the stack position
expect(data[targets[0]].index[2]).toBe(1);

annotation.state.removeAnnotation(probeAnnotation.annotationUID);
done();
});
};

element.addEventListener(Events.IMAGE_RENDERED, () => {
const index1 = [11, 20, 0];

const { imageData } = vp.getImageData();

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

const mouseDownEvt = new MouseEvent('mousedown', {
target: element,
buttons: 1,
pageX: pageX1,
pageY: pageY1,
clientX: clientX1,
clientY: clientY1,
});
const mouseUpEvt = new MouseEvent('mouseup');

performMouseDownAndUp(
element,
mouseDownEvt,
mouseUpEvt,
addEventListenerForAnnotationRendered
);
});

try {
vp.setStack([imageId0, imageId1], 1);
renderingEngine.render();
} catch (e) {
done.fail(e);
}
});

it('Should successfully click to put two probe tools on a canvas - 256 x 256', function (done) {
const element = createViewports(renderingEngine, {
viewportType: ViewportType.STACK,
Expand Down