Skip to content

Commit

Permalink
fix: windowLevel event trigger and initial voi range (#81)
Browse files Browse the repository at this point in the history
* fix initial voi range applied to stacks

* fix the initial voi in stack viewport
  • Loading branch information
sedghi authored Apr 20, 2022
1 parent 7847ea7 commit 38307d4
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 26 deletions.
2 changes: 1 addition & 1 deletion common/reviews/api/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1876,8 +1876,8 @@ type VoiModifiedEvent = CustomEvent_2<VoiModifiedEventDetail>;
// @public (undocumented)
type VoiModifiedEventDetail = {
viewportId: string;
volumeId: string;
range: VOIRange;
volumeId?: string;
};

// @public (undocumented)
Expand Down
2 changes: 1 addition & 1 deletion common/reviews/api/streaming-image-volume-loader.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1110,8 +1110,8 @@ type VoiModifiedEvent = CustomEvent_2<VoiModifiedEventDetail>;
// @public
type VoiModifiedEventDetail = {
viewportId: string;
volumeId: string;
range: VOIRange;
volumeId?: string;
};

// @public (undocumented)
Expand Down
2 changes: 1 addition & 1 deletion common/reviews/api/tools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3553,8 +3553,8 @@ type VoiModifiedEvent = CustomEvent_2<VoiModifiedEventDetail>;
// @public
type VoiModifiedEventDetail = {
viewportId: string;
volumeId: string;
range: VOIRange;
volumeId?: string;
};

// @public (undocumented)
Expand Down
90 changes: 71 additions & 19 deletions packages/core/src/RenderingEngine/StackViewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,22 @@ import resetCamera from './helpers/cpuFallback/rendering/resetCamera';
import { Transform } from './helpers/cpuFallback/rendering/transform';
import { getShouldUseCPURendering } from '../init';
import RequestType from '../enums/RequestType';
import { VoiModifiedEventDetail } from '../types/EventTypes';

const EPSILON = 1; // Slice Thickness

interface ImagePixelModule {
bitsAllocated: number;
bitsStored: number;
samplesPerPixel: number;
highBit: number;
photometricInterpretation: string;
pixelRepresentation: string;
windowWidth: number;
windowCenter: number;
modality: string;
}

interface ImageDataMetaData {
bitsAllocated: number;
numComps: number;
Expand All @@ -66,7 +79,7 @@ interface ImageDataMetaData {
spacing: Point3;
numVoxels: number;
imagePlaneModule: unknown;
imagePixelModule: unknown;
imagePixelModule: ImagePixelModule;
}

// TODO This needs to be exposed as its published to consumers.
Expand All @@ -89,6 +102,7 @@ class StackViewport extends Viewport implements IStackViewport {

// Viewport Properties
private voiRange: VOIRange;
private initialVOIRange: VOIRange;
private invert = false;
private interpolationType: InterpolationType;
private rotation = 0;
Expand Down Expand Up @@ -584,7 +598,7 @@ class StackViewport extends Viewport implements IStackViewport {
this.voiApplied = false;

this.setProperties({
voiRange: undefined,
voiRange: this.initialVOIRange,
rotation: 0,
interpolationType: InterpolationType.LINEAR,
invert: false,
Expand Down Expand Up @@ -830,7 +844,7 @@ class StackViewport extends Viewport implements IStackViewport {
};

const { lower, upper } = windowLevelUtil.toLowHighRange(wwToUse, wcToUse);
this.voiRange = { lower, upper };
voiRange = { lower, upper };
} else {
const { lower, upper } = voiRange;
const { windowCenter, windowWidth } = windowLevelUtil.toWindowLevel(
Expand All @@ -847,10 +861,16 @@ class StackViewport extends Viewport implements IStackViewport {

viewport.voi.windowWidth = windowWidth;
viewport.voi.windowCenter = windowCenter;
this.voiRange = voiRange;
}

this.voiApplied = true;
this.voiRange = voiRange;
const eventDetail: VoiModifiedEventDetail = {
viewportId: this.id,
range: voiRange,
};

triggerEvent(this.element, Events.VOI_MODIFIED, eventDetail);
}

private setVOIGPU(voiRange: VOIRange): void {
Expand All @@ -866,13 +886,20 @@ class StackViewport extends Viewport implements IStackViewport {
const imageData = volumeActor.getMapper().getInputData();
const range = imageData.getPointData().getScalars().getRange();
tfunc.setRange(range[0], range[1]);
this.voiRange = { lower: range[0], upper: range[1] };
voiRange = { lower: range[0], upper: range[1] };
} else {
const { lower, upper } = voiRange;
tfunc.setRange(lower, upper);
this.voiRange = voiRange;
}

this.voiApplied = true;
this.voiRange = voiRange;
const eventDetail: VoiModifiedEventDetail = {
viewportId: this.id,
range: voiRange,
};

triggerEvent(this.element, Events.VOI_MODIFIED, eventDetail);
}

/**
Expand Down Expand Up @@ -1028,16 +1055,15 @@ class StackViewport extends Viewport implements IStackViewport {
*
* @param image - cornerstone Image object
*/
private _createVTKImageData(image: IImage): void {
const {
origin,
direction,
dimensions,
spacing,
bitsAllocated,
numComps,
numVoxels,
} = this._getImageDataMetadata(image);
private _createVTKImageData({
origin,
direction,
dimensions,
spacing,
bitsAllocated,
numComps,
numVoxels,
}): void {
let pixelArray;
switch (bitsAllocated) {
case 8:
Expand Down Expand Up @@ -1091,6 +1117,7 @@ class StackViewport extends Viewport implements IStackViewport {
this.rotationCache = 0;
this.flipVertical = false;
this.flipHorizontal = false;
this.voiApplied = false;

this._resetProperties();

Expand Down Expand Up @@ -1531,9 +1558,28 @@ class StackViewport extends Viewport implements IStackViewport {
return;
}

const {
origin,
direction,
dimensions,
spacing,
bitsAllocated,
numComps,
numVoxels,
imagePixelModule,
} = this._getImageDataMetadata(image);

// 3b. If we cannot reuse the vtkImageData object (either the first render
// or the size has changed), create a new one
this._createVTKImageData(image);
this._createVTKImageData({
origin,
direction,
dimensions,
spacing,
bitsAllocated,
numComps,
numVoxels,
});

// Set the scalar data of the vtkImageData object from the Cornerstone
// Image's pixel data
Expand All @@ -1545,7 +1591,6 @@ class StackViewport extends Viewport implements IStackViewport {
this.setActors([{ uid: this.id, volumeActor: stackActor }]);
// Adjusting the camera based on slice axis. this is required if stack
// contains various image orientations (axial ct, sagittal xray)
const direction = this._imageData.getDirection() as Float32Array;
const { viewPlaneNormal, viewUp } = this._getCameraOrientation(direction);

this.setCameraNoEvent({ viewUp, viewPlaneNormal });
Expand All @@ -1562,7 +1607,14 @@ class StackViewport extends Viewport implements IStackViewport {
activeCamera.setFreezeFocalPoint(true);

// set voi for the first time
this.setProperties();
const { windowCenter, windowWidth } = imagePixelModule;
const voiRange =
typeof windowCenter === 'number' && typeof windowWidth === 'number'
? windowLevelUtil.toLowHighRange(windowWidth, windowCenter)
: undefined;

this.initialVOIRange = voiRange;
this.setProperties({ voiRange });

// Saving position of camera on render, to cache the panning
const { position } = this.getCamera();
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/types/EventTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ type CameraModifiedEventDetail = {
type VoiModifiedEventDetail = {
/** Viewport Unique ID in the renderingEngine */
viewportId: string;
/** Unique ID for the volume in the cache */
volumeId: string;
/** new VOI range */
range: VOIRange;
/** Unique ID for the volume in the cache */
volumeId?: string;
};

/**
Expand Down
5 changes: 3 additions & 2 deletions packages/tools/src/tools/WindowLevelTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,6 @@ export default class WindowLevelTool extends BaseTool {
range: newRange,
};

triggerEvent(element, Enums.Events.VOI_MODIFIED, eventDetail);

if (viewport instanceof StackViewport) {
viewport.setProperties({
voiRange: newRange,
Expand All @@ -111,6 +109,9 @@ export default class WindowLevelTool extends BaseTool {
return;
}

// Only trigger event for volume since the stack event is triggered inside
// the stackViewport, Todo: we need the setProperties API on the volume viewport
triggerEvent(element, Enums.Events.VOI_MODIFIED, eventDetail);
rgbTransferFunction.setRange(newRange.lower, newRange.upper);

viewportsContainingVolumeUID.forEach((vp) => {
Expand Down

0 comments on commit 38307d4

Please sign in to comment.