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(PT measurement units): Non-SUV scaled, but pre-scaled PTs should show proper units #686

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
22 changes: 10 additions & 12 deletions common/reviews/api/tools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ export class CircleROITool extends AnnotationTool {
// (undocumented)
addNewAnnotation: (evt: EventTypes_2.InteractionEventType) => CircleROIAnnotation;
// (undocumented)
_calculateCachedStats: (annotation: any, viewport: any, renderingEngine: any, enabledElement: any) => any;
_calculateCachedStats: (annotation: any, viewport: any, renderingEngine: any, enabledElement: any, modalityUnitOptions: ModalityUnitOptions) => any;
// (undocumented)
cancel: (element: HTMLDivElement) => any;
// (undocumented)
Expand All @@ -700,7 +700,7 @@ export class CircleROITool extends AnnotationTool {
// (undocumented)
_endCallback: (evt: EventTypes_2.InteractionEventType) => void;
// (undocumented)
_getTextLines: (data: any, targetId: string, isPreScaled: boolean, isSuvScaled: boolean) => string[];
_getTextLines: (data: any, targetId: string) => string[];
// (undocumented)
handleSelectedCallback: (evt: EventTypes_2.InteractionEventType, annotation: CircleROIAnnotation, handle: ToolHandle) => void;
// (undocumented)
Expand Down Expand Up @@ -1652,7 +1652,7 @@ export class EllipticalROITool extends AnnotationTool {
// (undocumented)
addNewAnnotation: (evt: EventTypes_2.InteractionEventType) => EllipticalROIAnnotation;
// (undocumented)
_calculateCachedStats: (annotation: any, viewport: any, renderingEngine: any, enabledElement: any) => any;
_calculateCachedStats: (annotation: any, viewport: any, renderingEngine: any, enabledElement: any, modalityUnitOptions: ModalityUnitOptions) => any;
// (undocumented)
cancel: (element: HTMLDivElement) => any;
// (undocumented)
Expand Down Expand Up @@ -1683,7 +1683,7 @@ export class EllipticalROITool extends AnnotationTool {
// (undocumented)
_getCanvasEllipseCenter(ellipseCanvasPoints: Types_2.Point2[]): Types_2.Point2;
// (undocumented)
_getTextLines: (data: any, targetId: string, isPreScaled: boolean, isSuvScaled: boolean) => string[];
_getTextLines: (data: any, targetId: string) => string[];
// (undocumented)
handleSelectedCallback: (evt: EventTypes_2.InteractionEventType, annotation: EllipticalROIAnnotation, handle: ToolHandle) => void;
// (undocumented)
Expand Down Expand Up @@ -3670,13 +3670,13 @@ export class PlanarFreehandROITool extends AnnotationTool {
// (undocumented)
addNewAnnotation: (evt: EventTypes_2.InteractionEventType) => PlanarFreehandROIAnnotation;
// (undocumented)
_calculateCachedStats: (annotation: any, viewport: any, renderingEngine: any, enabledElement: any) => any;
_calculateCachedStats: (annotation: any, viewport: any, renderingEngine: any, enabledElement: any, modalityUnitOptions: ModalityUnitOptions) => any;
// (undocumented)
cancel: (element: HTMLDivElement) => void;
// (undocumented)
filterInteractableAnnotationsForElement(element: HTMLDivElement, annotations: Annotations): Annotations | undefined;
// (undocumented)
_getTextLines: (data: any, targetId: string, isPreScaled: boolean, isSuvScaled: boolean) => string[];
_getTextLines: (data: any, targetId: string) => string[];
// (undocumented)
handleSelectedCallback: (evt: EventTypes_2.InteractionEventType, annotation: PlanarFreehandROIAnnotation, handle: ToolHandle) => void;
// (undocumented)
Expand Down Expand Up @@ -3822,7 +3822,7 @@ export class ProbeTool extends AnnotationTool {
// (undocumented)
addNewAnnotation: (evt: EventTypes_2.InteractionEventType) => ProbeAnnotation;
// (undocumented)
_calculateCachedStats(annotation: any, renderingEngine: any, enabledElement: any): any;
_calculateCachedStats(annotation: any, renderingEngine: any, enabledElement: any, modalityUnitOptions: ModalityUnitOptions): any;
// (undocumented)
cancel: (element: HTMLDivElement) => any;
// (undocumented)
Expand All @@ -3845,9 +3845,7 @@ export class ProbeTool extends AnnotationTool {
// (undocumented)
getHandleNearImagePoint(element: HTMLDivElement, annotation: ProbeAnnotation, canvasCoords: Types_2.Point2, proximity: number): ToolHandle | undefined;
// (undocumented)
_getTextLines(data: any, targetId: string, isPreScaled: boolean, isSuvScaled: boolean): string[] | undefined;
// (undocumented)
_getValueForModality(value: any, imageVolume: any, modality: any): {};
_getTextLines(data: any, targetId: string): string[] | undefined;
// (undocumented)
handleSelectedCallback(evt: EventTypes_2.InteractionEventType, annotation: ProbeAnnotation): void;
// (undocumented)
Expand Down Expand Up @@ -4108,7 +4106,7 @@ export class RectangleROITool extends AnnotationTool {
// (undocumented)
addNewAnnotation: (evt: EventTypes_2.InteractionEventType) => RectangleROIAnnotation;
// (undocumented)
_calculateCachedStats: (annotation: any, viewPlaneNormal: any, viewUp: any, renderingEngine: any, enabledElement: any) => any;
_calculateCachedStats: (annotation: any, viewPlaneNormal: any, viewUp: any, renderingEngine: any, enabledElement: any, modalityUnitOptions: any) => any;
// (undocumented)
cancel: (element: HTMLDivElement) => any;
// (undocumented)
Expand Down Expand Up @@ -4136,7 +4134,7 @@ export class RectangleROITool extends AnnotationTool {
height: number;
};
// (undocumented)
_getTextLines: (data: any, targetId: string, isPreScaled: boolean, isSuvScaled: boolean) => string[] | undefined;
_getTextLines: (data: any, targetId: string) => string[] | undefined;
// (undocumented)
handleSelectedCallback: (evt: EventTypes_2.InteractionEventType, annotation: RectangleROIAnnotation, handle: ToolHandle) => void;
// (undocumented)
Expand Down
61 changes: 33 additions & 28 deletions packages/tools/src/tools/annotation/CircleROITool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ import {
import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds';
import { pointInShapeCallback } from '../../utilities';
import { StyleSpecifier } from '../../types/AnnotationStyle';
import { getModalityUnit } from '../../utilities/getModalityUnit';
import {
ModalityUnitOptions,
getModalityUnit,
} from '../../utilities/getModalityUnit';
import { isViewportPreScaled } from '../../utilities/viewport/isViewportPreScaled';
import {
getCanvasCircleCorners,
Expand Down Expand Up @@ -661,6 +664,16 @@ class CircleROITool extends AnnotationTool {

const { centerPointRadius } = this.configuration;

const modalityUnitOptions = {
isPreScaled: isViewportPreScaled(viewport, targetId),

isSuvScaled: this.isSuvScaled(
viewport,
targetId,
annotation.metadata.referencedImageId
),
};

// If cachedStats does not exist, or the unit is missing (as part of import/hydration etc.),
// force to recalculate the stats from the points
if (
Expand All @@ -683,14 +696,16 @@ class CircleROITool extends AnnotationTool {
annotation,
viewport,
renderingEngine,
enabledElement
enabledElement,
modalityUnitOptions
);
} else if (annotation.invalidated) {
this._throttledCalculateCachedStats(
annotation,
viewport,
renderingEngine,
enabledElement
enabledElement,
modalityUnitOptions
);
// If the invalidated data is as a result of volumeViewport manipulation
// of the tools, we need to invalidate the related viewports data, so that
Expand Down Expand Up @@ -797,20 +812,7 @@ class CircleROITool extends AnnotationTool {

renderStatus = true;

const isPreScaled = isViewportPreScaled(viewport, targetId);

const isSuvScaled = this.isSuvScaled(
viewport,
targetId,
annotation.metadata.referencedImageId
);

const textLines = this._getTextLines(
data,
targetId,
isPreScaled,
isSuvScaled
);
const textLines = this._getTextLines(data, targetId);
if (!textLines || textLines.length === 0) {
continue;
}
Expand Down Expand Up @@ -854,12 +856,7 @@ class CircleROITool extends AnnotationTool {
return renderStatus;
};

_getTextLines = (
data,
targetId: string,
isPreScaled: boolean,
isSuvScaled: boolean
): string[] => {
_getTextLines = (data, targetId: string): string[] => {
const cachedVolumeStats = data.cachedStats[targetId];
const {
radius,
Expand All @@ -871,10 +868,10 @@ class CircleROITool extends AnnotationTool {
isEmptyArea,
Modality,
areaUnit,
modalityUnit,
} = cachedVolumeStats;

const textLines: string[] = [];
const unit = getModalityUnit(Modality, isPreScaled, isSuvScaled);

if (radius) {
const radiusLine = isEmptyArea
Expand All @@ -891,15 +888,15 @@ class CircleROITool extends AnnotationTool {
}

if (mean) {
textLines.push(`Mean: ${mean.toFixed(2)} ${unit}`);
textLines.push(`Mean: ${mean.toFixed(2)} ${modalityUnit}`);
}

if (max) {
textLines.push(`Max: ${max.toFixed(2)} ${unit}`);
textLines.push(`Max: ${max.toFixed(2)} ${modalityUnit}`);
}

if (stdDev) {
textLines.push(`Std Dev: ${stdDev.toFixed(2)} ${unit}`);
textLines.push(`Std Dev: ${stdDev.toFixed(2)} ${modalityUnit}`);
}

return textLines;
Expand All @@ -909,7 +906,8 @@ class CircleROITool extends AnnotationTool {
annotation,
viewport,
renderingEngine,
enabledElement
enabledElement,
modalityUnitOptions: ModalityUnitOptions
) => {
const data = annotation.data;
const { viewportId, renderingEngineId } = enabledElement;
Expand Down Expand Up @@ -1037,6 +1035,12 @@ class CircleROITool extends AnnotationTool {
stdDev /= count;
stdDev = Math.sqrt(stdDev);

const modalityUnit = getModalityUnit(
metadata.Modality,
annotation.metadata.referencedImageId,
modalityUnitOptions
);

cachedStats[targetId] = {
Modality: metadata.Modality,
area,
Expand All @@ -1048,6 +1052,7 @@ class CircleROITool extends AnnotationTool {
radius: worldWidth / 2,
radiusUnit: hasPixelSpacing ? 'mm' : 'px',
perimeter: 2 * Math.PI * (worldWidth / 2),
modalityUnit,
};
} else {
this.isHandleOutsideImage = true;
Expand Down
39 changes: 23 additions & 16 deletions packages/tools/src/tools/annotation/DragProbeTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,36 @@ class DragProbeTool extends ProbeTool {

const color = this.getStyle('color', styleSpecifier, annotation);

const modalityUnitOptions = {
isPreScaled: isViewportPreScaled(viewport, targetId),

isSuvScaled: this.isSuvScaled(
viewport,
targetId,
annotation.metadata.referencedImageId
),
};

if (!data.cachedStats[targetId]) {
data.cachedStats[targetId] = {
Modality: null,
index: null,
value: null,
};

this._calculateCachedStats(annotation, renderingEngine, enabledElement);
this._calculateCachedStats(
annotation,
renderingEngine,
enabledElement,
modalityUnitOptions
);
} else if (annotation.invalidated) {
this._calculateCachedStats(annotation, renderingEngine, enabledElement);
this._calculateCachedStats(
annotation,
renderingEngine,
enabledElement,
modalityUnitOptions
);
}

// If rendering engine has been destroyed while rendering
Expand All @@ -185,20 +205,7 @@ class DragProbeTool extends ProbeTool {

renderStatus = true;

const isPreScaled = isViewportPreScaled(viewport, targetId);

const isSuvScaled = this.isSuvScaled(
viewport,
targetId,
annotation.metadata.referencedImageId
);

const textLines = this._getTextLines(
data,
targetId,
isPreScaled,
isSuvScaled
);
const textLines = this._getTextLines(data, targetId);
if (textLines) {
const textCanvasCoordinates = [
canvasCoordinates[0] + 6,
Expand Down
Loading