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

feat: cachedStats to store imageId and volumeId #75

Merged
merged 6 commits into from
Apr 13, 2022
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
8 changes: 8 additions & 0 deletions common/reviews/api/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,10 @@ interface IStackViewport extends IViewport {
// (undocumented)
getRenderer(): any;
// (undocumented)
hasImageId: (imageId: string) => boolean;
// (undocumented)
hasImageURI: (imageURI: string) => boolean;
// (undocumented)
modality: string;
// (undocumented)
resetCamera(resetPanZoomForViewPlane?: boolean): boolean;
Expand Down Expand Up @@ -1572,6 +1576,10 @@ export class StackViewport extends Viewport implements IStackViewport {
// (undocumented)
getRenderer(): any;
// (undocumented)
hasImageId: (imageId: string) => boolean;
// (undocumented)
hasImageURI: (imageURI: string) => boolean;
// (undocumented)
modality: string;
// (undocumented)
removeAllActors(): void;
Expand Down
2 changes: 2 additions & 0 deletions common/reviews/api/streaming-image-volume-loader.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,8 @@ interface IStackViewport extends IViewport {
getImageIds: () => string[];
getProperties: () => StackViewportProperties;
getRenderer(): any;
hasImageId: (imageId: string) => boolean;
hasImageURI: (imageURI: string) => boolean;
// (undocumented)
modality: string;
resetCamera(resetPanZoomForViewPlane?: boolean): boolean;
Expand Down
11 changes: 6 additions & 5 deletions common/reviews/api/tools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ export abstract class AnnotationTool extends BaseTool {
// (undocumented)
getLinkedTextBoxStyle(settings: Settings, annotation?: Annotation): Record<string, unknown>;
// (undocumented)
protected getReferencedImageId(viewport: Types_2.IStackViewport | Types_2.IVolumeViewport, worldPos: Types_2.Point3, viewPlaneNormal: Types_2.Point3, viewUp: Types_2.Point3): string;
// (undocumented)
getStyle(settings: Settings, property: string, annotation?: Annotation): unknown;
// (undocumented)
abstract handleSelectedCallback(evt: EventTypes_2.MouseDownEventType, annotation: Annotation, handle: ToolHandle, interactionType: InteractionTypes): void;
Expand Down Expand Up @@ -217,10 +219,7 @@ export abstract class BaseTool implements IBaseTool {
// (undocumented)
protected getTargetId(viewport: Types_2.IViewport): string | undefined;
// (undocumented)
protected getTargetIdViewportAndImage(targetId: string, renderingEngine: Types_2.IRenderingEngine): {
viewport: Types_2.IViewport;
image: Types_2.IImageData;
};
protected getTargetIdImage(targetId: string, renderingEngine: Types_2.IRenderingEngine): Types_2.IImageData | Types_2.CPUIImageData | Types_2.IImageVolume;
// (undocumented)
getToolName(): string;
// (undocumented)
Expand Down Expand Up @@ -1805,6 +1804,8 @@ interface IStackViewport extends IViewport {
getImageIds: () => string[];
getProperties: () => StackViewportProperties;
getRenderer(): any;
hasImageId: (imageId: string) => boolean;
hasImageURI: (imageURI: string) => boolean;
// (undocumented)
modality: string;
resetCamera(resetPanZoomForViewPlane?: boolean): boolean;
Expand Down Expand Up @@ -2884,7 +2885,7 @@ type ScalingParameters = {
};

// @public (undocumented)
function scrollThroughStack(evt: MouseWheelEventType | MouseDragEventType, deltaFrames: number, volumeId: string, invert?: boolean): void;
function scrollThroughStack(viewport: Types_2.IStackViewport | Types_2.IVolumeViewport, targetId: string, deltaFrames: number, invert?: boolean): void;

// @public (undocumented)
type Segmentation = {
Expand Down
24 changes: 24 additions & 0 deletions packages/core/src/RenderingEngine/StackViewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
isEqual,
invertRgbTransferFunction,
windowLevel as windowLevelUtil,
imageIdToURI,
} from '../utilities';
import {
Point2,
Expand Down Expand Up @@ -1895,6 +1896,29 @@ class StackViewport extends Viewport implements IStackViewport {
return this.imageIds[this.currentImageIdIndex];
};

/**
* Returns true if the viewport contains the given imageId
* @param imageId - imageId
* @returns boolean if imageId is in viewport
*/
public hasImageId = (imageId: string): boolean => {
return this.imageIds.includes(imageId);
};

/**
* Returns true if the viewport contains the given imageURI (no data loader scheme)
* @param imageURI - imageURI
* @returns boolean if imageURI is in viewport
*/
public hasImageURI = (imageURI: string): boolean => {
const imageIds = this.imageIds;
for (let i = 0; i < imageIds.length; i++) {
if (imageIdToURI(imageIds[i]) === imageURI) return true;
}

return false;
};

/**
* If the renderer is CPU based, throw an error. Otherwise, returns the `vtkRenderer` responsible for rendering the `Viewport`.
*
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/types/IStackViewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ export default interface IStackViewport extends IViewport {
* Returns the list of image Ids for the current viewport
*/
getImageIds: () => string[];
/**
* Returns true if the viewport contains the imageId
*/
hasImageId: (imageId: string) => boolean;
/**
* Returns true if the viewport contains the imageURI
*/
hasImageURI: (imageURI: string) => boolean;
/**
* Returns the currently rendered imageId
*/
Expand Down
12 changes: 10 additions & 2 deletions packages/tools/src/tools/MIPJumpToClickTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,15 @@ export default class MIPJumpToClickTool extends BaseTool {
const { viewport, renderingEngine } = enabledElement;

// 2. Getting the target volume that is clicked on
const targetVolumeId = this.getTargetId(viewport as Types.IVolumeViewport);
const targetId = this.getTargetId(viewport as Types.IVolumeViewport);

if (!targetId.startsWith('volumeId')) {
throw new Error(
`MIPJumpToClickTool: targetId is not a volumeId, you should only use MIPJumpToClickTool with a volumeId as the targetId`
);
}

const volumeId = targetId.split('volumeId:')[1];

// 3. Criteria function to search for the point (maximum intensity)
let maxIntensity = -Infinity;
Expand All @@ -60,7 +68,7 @@ export default class MIPJumpToClickTool extends BaseTool {
const brightestPoint = getPointInLineOfSightWithCriteria(
viewport as Types.IVolumeViewport,
currentPoints.world,
targetVolumeId,
volumeId,
maxFn
);

Expand Down
4 changes: 2 additions & 2 deletions packages/tools/src/tools/StackScrollTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ export default class StackScrollTool extends BaseTool {
const { deltaPoints, viewportId, renderingEngineId } = evt.detail;
const deltaFrames = deltaPoints.canvas[1];
const { viewport } = getEnabledElementByIds(viewportId, renderingEngineId);
const volumeId = this.getTargetId(viewport);
const targetId = this.getTargetId(viewport);
const { invert } = this.configuration;

scrollThroughStack(evt, deltaFrames, volumeId, invert);
scrollThroughStack(viewport, targetId, deltaFrames, invert);
}
}
9 changes: 6 additions & 3 deletions packages/tools/src/tools/StackScrollToolMouseWheelTool.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BaseTool } from './base';
import { scrollThroughStack } from '../utilities/stackScrollTool';
import { MouseWheelEventType } from '../types/EventTypes';
import { getEnabledElement } from '@cornerstonejs/core';

/**
* The StackScrollMouseWheelTool is a tool that allows the user to scroll through a
Expand All @@ -22,9 +23,11 @@ export default class StackScrollMouseWheelTool extends BaseTool {
}

mouseWheelCallback(evt: MouseWheelEventType): void {
const { wheel } = evt.detail;
const { wheel, element } = evt.detail;
const { direction: deltaFrames } = wheel;
const { invert, volumeId } = this.configuration;
scrollThroughStack(evt, deltaFrames, volumeId, invert);
const { invert } = this.configuration;
const { viewport } = getEnabledElement(element);
const targetId = this.getTargetId(viewport);
scrollThroughStack(viewport, targetId, deltaFrames, invert);
}
}
3 changes: 2 additions & 1 deletion packages/tools/src/tools/WindowLevelTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ export default class WindowLevelTool extends BaseTool {
let useDynamicRange = false;

if (viewport instanceof VolumeViewport) {
volumeId = this.getTargetId(viewport as Types.IVolumeViewport);
const targetId = this.getTargetId(viewport as Types.IVolumeViewport);
volumeId = targetId.split('volumeId:')[1];
({ volumeActor } = viewport.getActor(volumeId));
rgbTransferFunction = volumeActor.getProperty().getRGBTransferFunction(0);
viewportsContainingVolumeUID =
Expand Down
32 changes: 8 additions & 24 deletions packages/tools/src/tools/annotation/BidirectionalTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,34 +144,21 @@ export default class BidirectionalTool extends AnnotationTool {
const camera = viewport.getCamera();
const { viewPlaneNormal, viewUp } = camera;

let referencedImageId;
if (viewport instanceof StackViewport) {
referencedImageId =
viewport.getCurrentImageId && viewport.getCurrentImageId();
} else {
const volumeId = this.getTargetId(viewport);
const imageVolume = cache.getVolume(volumeId);
referencedImageId = csUtils.getClosestImageId(
imageVolume,
worldPos,
viewPlaneNormal,
viewUp
);
}

if (referencedImageId) {
const colonIndex = referencedImageId.indexOf(':');
referencedImageId = referencedImageId.substring(colonIndex + 1);
}
const referencedImageId = this.getReferencedImageId(
viewport,
worldPos,
viewPlaneNormal,
viewUp
);

const annotation: BidirectionalAnnotation = {
highlighted: true,
invalidated: true,
metadata: {
toolName: BidirectionalTool.toolName,
viewPlaneNormal: <Types.Point3>[...viewPlaneNormal],
viewUp: <Types.Point3>[...viewUp],
FrameOfReferenceUID: viewport.getFrameOfReferenceUID(),
toolName: BidirectionalTool.toolName,
referencedImageId,
},
data: {
Expand Down Expand Up @@ -1190,10 +1177,7 @@ export default class BidirectionalTool extends AnnotationTool {
for (let i = 0; i < targetIds.length; i++) {
const targetId = targetIds[i];

const { image } = this.getTargetIdViewportAndImage(
targetId,
renderingEngine
);
const image = this.getTargetIdImage(targetId, renderingEngine);

const { imageData, dimensions } = image;

Expand Down
68 changes: 28 additions & 40 deletions packages/tools/src/tools/annotation/EllipticalROITool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,37 +158,22 @@ export default class EllipticalROITool extends AnnotationTool {
const camera = viewport.getCamera();
const { viewPlaneNormal, viewUp } = camera;

let referencedImageId;
if (viewport instanceof StackViewport) {
referencedImageId =
viewport.getCurrentImageId && viewport.getCurrentImageId();
} else {
const volumeId = this.getTargetId(viewport);
const imageVolume = cache.getVolume(volumeId);
referencedImageId = csUtils.getClosestImageId(
imageVolume,
worldPos,
viewPlaneNormal,
viewUp
);
}

if (referencedImageId) {
const colonIndex = referencedImageId.indexOf(':');
referencedImageId = referencedImageId.substring(colonIndex + 1);
}

this.isDrawing = true;
const referencedImageId = this.getReferencedImageId(
viewport,
worldPos,
viewPlaneNormal,
viewUp
);

const annotation = {
highlighted: true,
invalidated: true,
metadata: {
toolName: EllipticalROITool.toolName,
viewPlaneNormal: <Types.Point3>[...viewPlaneNormal],
viewUp: <Types.Point3>[...viewUp],
FrameOfReferenceUID: viewport.getFrameOfReferenceUID(),
referencedImageId,
toolName: EllipticalROITool.toolName,
},
data: {
label: '',
Expand Down Expand Up @@ -780,23 +765,29 @@ export default class EllipticalROITool extends AnnotationTool {
if (viewport instanceof VolumeViewport) {
const { referencedImageId } = annotation.metadata;

// todo: this is not efficient, but necessary
// invalidate all the relevant stackViewports if they are not
// at the referencedImageId
const viewports = renderingEngine.getViewports();
viewports.forEach((vp) => {
const stackTargetId = this.getTargetId(vp);
// only delete the cachedStats for the stackedViewports if the tool
// is dragged inside the volume and the stackViewports are not at the
// referencedImageId for the tool
if (
vp instanceof StackViewport &&
!vp.getCurrentImageId().includes(referencedImageId) &&
data.cachedStats[stackTargetId]
) {
delete data.cachedStats[stackTargetId];
for (const targetId in data.cachedStats) {
if (targetId.startsWith('imageId')) {
const viewports = renderingEngine.getStackViewports();

const invalidatedStack = viewports.find((vp) => {
// The stack viewport that contains the imageId but is not
// showing it currently
const referencedImageURI =
csUtils.imageIdToURI(referencedImageId);
const hasImageURI = vp.hasImageURI(referencedImageURI);
const currentImageURI = csUtils.imageIdToURI(
vp.getCurrentImageId()
);
return hasImageURI && currentImageURI !== referencedImageURI;
});

if (invalidatedStack) {
delete data.cachedStats[targetId];
}
}
});
}
}
}

Expand Down Expand Up @@ -958,10 +949,7 @@ export default class EllipticalROITool extends AnnotationTool {
for (let i = 0; i < targetIds.length; i++) {
const targetId = targetIds[i];

const { image } = this.getTargetIdViewportAndImage(
targetId,
renderingEngine
);
const image = this.getTargetIdImage(targetId, renderingEngine);

const { dimensions, imageData, metadata } = image;

Expand Down
Loading