Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix/multiframe wadorui #603

Merged
merged 5 commits into from
May 9, 2023
Merged
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
4 changes: 4 additions & 0 deletions common/reviews/api/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1526,6 +1526,9 @@ function isImageActor(actorEntry: Types.ActorEntry): boolean;
// @public (undocumented)
function isOpposite(v1: Point3, v2: Point3, tolerance?: number): boolean;

// @public (undocumented)
const isPTPrescaledWithSUV: (image: IImage) => number;

// @public (undocumented)
interface IStackViewport extends IViewport {
// (undocumented)
Expand Down Expand Up @@ -2428,6 +2431,7 @@ declare namespace utilities {
snapFocalPointToSlice,
getImageSliceDataForVolumeViewport,
isImageActor,
isPTPrescaledWithSUV,
actorIsA,
getViewportsWithImageURI,
getClosestStackImageIndexForPoint,
Expand Down
5 changes: 4 additions & 1 deletion common/reviews/api/tools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5551,11 +5551,14 @@ export class WindowLevelTool extends BaseTool {
upper: number;
};
// (undocumented)
getPTNewRange({ deltaPointsCanvas, lower, upper, clientHeight }: {
getPTScaledNewRange({ deltaPointsCanvas, lower, upper, clientHeight, viewport, volumeId, isPreScaled, }: {
deltaPointsCanvas: any;
lower: any;
upper: any;
clientHeight: any;
viewport: any;
volumeId: any;
isPreScaled: any;
}): {
lower: any;
upper: any;
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/utilities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import applyPreset from './applyPreset';
import deepMerge from './deepMerge';
import getScalingParameters from './getScalingParameters';
import getScalarDataType from './getScalarDataType';
import isPTPrescaledWithSUV from './isPTPrescaledWithSUV';

// name spaces
import * as planar from './planar';
Expand Down Expand Up @@ -89,6 +90,7 @@ export {
snapFocalPointToSlice,
getImageSliceDataForVolumeViewport,
isImageActor,
isPTPrescaledWithSUV,
actorIsA,
getViewportsWithImageURI,
getClosestStackImageIndexForPoint,
Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/utilities/isPTPrescaledWithSUV.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { IImage } from '../types';

const isPTPrescaledWithSUV = (image: IImage) => {
return image.preScale?.scaled && image.preScale.scalingParameters?.suvbw;
};

export default isPTPrescaledWithSUV;
10 changes: 5 additions & 5 deletions packages/core/src/utilities/renderToCanvasGPU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import StackViewport from '../RenderingEngine/StackViewport';
import { IImage } from '../types';
import { getRenderingEngine } from '../RenderingEngine/getRenderingEngine';
import RenderingEngine from '../RenderingEngine';
import isPTPrescaledWithSUV from './isPTPrescaledWithSUV';

/**
* Renders an cornerstone image to a Canvas. This method will handle creation
Expand Down Expand Up @@ -112,7 +113,10 @@ export default function renderToCanvasGPU(
element.addEventListener(Events.IMAGE_RENDERED, onImageRendered);
viewport.renderImageObject(image);

if (modality === 'PT' && !_isPTImagePreScaledWithSUV(image)) {
// force a reset camera to center the image
viewport.resetCamera();

if (modality === 'PT' && !isPTPrescaledWithSUV(image)) {
viewport.setProperties({
voiRange: {
lower: image.minPixelValue,
Expand All @@ -124,7 +128,3 @@ export default function renderToCanvasGPU(
viewport.render();
});
}

const _isPTImagePreScaledWithSUV = (image: IImage) => {
return image.preScale.scaled && image.preScale.scalingParameters.suvbw;
};
17 changes: 16 additions & 1 deletion packages/dicomImageLoader/src/imageLoader/wadouri/loadImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ function addDecache(imageLoadObject: Types.IImageLoadObject, imageId: string) {
};
}

/**
* Given the dataSetPromise and imageId this will return a promise to be
* resolved with an image object containing the loaded image.
*
sedghi marked this conversation as resolved.
Show resolved Hide resolved
* @param dataSetPromise - A promise that resolves to a DataSet object.
* @param imageId - The imageId of the image to be loaded.
* @param frame - The frame number to be loaded in case of multiframe. it should
* be noted that this is used to extract the pixelData from dicomParser and
* dicomParser is 0-based index (the first pixelData is frame 0); however,
* in metadata and imageId frame is 1-based index (the first frame is frame 1).
* @param sharedCacheKey - A key to be used to cache the loaded image.
* @param options - Options to be used when loading the image.
* @param callbacks - Callbacks to be called when the image is loaded.
* @returns An object containing a promise to be resolved with the loaded image
*/
function loadImageFromPromise(
dataSetPromise: Promise<DataSet>,
imageId: string,
Expand Down Expand Up @@ -179,7 +194,7 @@ function loadImage(
return loadImageFromDataSet(
dataSet,
imageId,
parsedImageId.frame,
parsedImageId.pixelDataFrame,
parsedImageId.url,
options
);
Expand Down
18 changes: 15 additions & 3 deletions packages/dicomImageLoader/src/imageLoader/wadouri/parseImageId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export interface CornerstoneImageUrl {
scheme: string;
url: string;
frame: number;
pixelDataFrame: number;
}

function parseImageId(imageId: string): CornerstoneImageUrl {
Expand All @@ -14,16 +15,27 @@ function parseImageId(imageId: string): CornerstoneImageUrl {
let frame;

if (frameIndex !== -1) {
const frameStr = url.substr(frameIndex + 6);
const frameStr = url.substring(frameIndex + 6);

frame = parseInt(frameStr, 10);
url = url.substr(0, frameIndex - 1);
url = url.substring(0, frameIndex - 1);
}

const scheme = imageId.substring(0, firstColonIndex);
/**
* Why we adjust frameNumber? since in the above we are extracting the
* frame number from the imageId (from the metadata), and the frame number
* starts from 1, but in the loader which uses the dicomParser
* the frame number starts from 0.
*/

const adjustedFrame = frame !== undefined ? frame - 1 : undefined;

return {
scheme: imageId.substr(0, firstColonIndex),
scheme,
url,
frame,
pixelDataFrame: adjustedFrame,
};
}

Expand Down
33 changes: 27 additions & 6 deletions packages/tools/src/tools/WindowLevelTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ class WindowLevelTool extends BaseTool {
modality = viewport.modality;
({ lower, upper } = properties.voiRange);
const { preScale } = viewport.getImageData();
isPreScaled = preScale.scaled;
isPreScaled =
preScale.scaled && preScale.scalingParameters?.suvbw !== undefined;
} else {
throw new Error('Viewport is not a valid type');
}
Expand All @@ -74,12 +75,15 @@ class WindowLevelTool extends BaseTool {
// the x direction. For other modalities, use the canvas delta in both
// directions, and if the viewport is a volumeViewport, the multiplier
// is calculate using the volume min and max.
if (modality === PT && isPreScaled) {
newRange = this.getPTNewRange({
if (modality === PT) {
newRange = this.getPTScaledNewRange({
deltaPointsCanvas: deltaPoints.canvas,
lower,
upper,
clientHeight: element.clientHeight,
isPreScaled,
viewport,
volumeId,
});
} else {
newRange = this.getNewRange({
Expand Down Expand Up @@ -112,13 +116,30 @@ class WindowLevelTool extends BaseTool {
}
}

getPTNewRange({ deltaPointsCanvas, lower, upper, clientHeight }) {
getPTScaledNewRange({
deltaPointsCanvas,
lower,
upper,
clientHeight,
viewport,
volumeId,
isPreScaled,
}) {
let multiplier = DEFAULT_MULTIPLIER;

if (isPreScaled) {
multiplier = 5 / clientHeight;
} else {
multiplier =
this._getMultiplierFromDynamicRange(viewport, volumeId) ||
DEFAULT_MULTIPLIER;
}

const deltaY = deltaPointsCanvas[1];
const multiplier = 5 / clientHeight;
const wcDelta = deltaY * multiplier;

upper -= wcDelta;
upper = Math.max(upper, 0.1);
upper = isPreScaled ? Math.max(upper, 0.1) : upper;

return { lower, upper };
}
Expand Down