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
55 changes: 55 additions & 0 deletions packages/ai/src/ONNXSegmentationController.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import ONNXSegmentationController from './ONNXSegmentationController';

jest.mock('onnxruntime-web/webgpu', () => ({
__esModule: true,
default: { env: { wasm: {} } },
}));

/**
* With auto segment mode on, every render of the controller's viewport runs
* the propagation step. `LabelmapSlicePropagationTool` re-points the controller
* at whichever viewport becomes active, so that render can come from a viewport
* that has no segmentation of its own.
*/
describe('ONNXSegmentationController auto segment mode', () => {
const viewportWithoutSegmentation = {
id: 'viewport-without-segmentation',
getCurrentImageId: () => 'imageId:2',
getViewReferenceId: () => undefined,
getCurrentImageIdIndex: () => 1,
getImageIds: () => ['imageId:1', 'imageId:2', 'imageId:3'],
};

it('renders a viewport with no active segmentation without throwing', () => {
const controller = new ONNXSegmentationController({
autoSegmentMode: true,
});
controller.enabled = true;
const internals = controller as unknown as {
viewport: typeof viewportWithoutSegmentation;
viewportRenderedListener: (event?: unknown) => void;
};
internals.viewport = viewportWithoutSegmentation;

expect(() => internals.viewportRenderedListener()).not.toThrow();
});

it('does not carry propagation points over to the next viewport', () => {
const controller = new ONNXSegmentationController({
autoSegmentMode: true,
});
const internals = controller as unknown as { randomPoints: unknown[] };
// Left over from painting on the previous viewport; decoding them against
// the next one previews into a segmentation that viewport may not have.
internals.randomPoints = [[10, 20, 30]];
// No model is loaded here, so there is nothing for it to encode.
jest.spyOn(controller, 'tryLoad').mockImplementation(() => undefined);

controller.initViewport({
...viewportWithoutSegmentation,
element: document.createElement('div'),
});

expect(internals.randomPoints).toEqual([]);
});
});
9 changes: 9 additions & 0 deletions packages/ai/src/ONNXSegmentationController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,9 @@ export default class ONNXSegmentationController {
this.disconnectViewport(this.viewport);
}
this.currentImage = null;
// These are world points on the previous viewport's segmentation; decoding
// them against this viewport would preview into a segmentation it lacks.
this.randomPoints = [];
this.viewport = viewport;

const brushInstance = new LabelmapBaseTool(
Expand Down Expand Up @@ -706,6 +709,12 @@ export default class ONNXSegmentationController {
viewport.id
);

// The controller follows whichever viewport the tool was pointed at, and
// that one need not have a segmentation yet - nothing to propagate there.
if (!segmentation) {
return;
}

const segmentIndex =
cornerstoneTools.segmentation.segmentIndex.getActiveSegmentIndex(
segmentation.segmentationId
Expand Down