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(DICOM Overlay): The overlay data wasn't being refreshed on change #3793

Merged
merged 4 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions extensions/cornerstone/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { id } from './id';
import * as csWADOImageLoader from './initWADOImageLoader.js';
import { measurementMappingUtils } from './utils/measurementServiceMappings';
import type { PublicViewportOptions } from './services/ViewportService/Viewport';
import ImageOverlayViewerTool from './tools/ImageOverlayViewerTool';

const Component = React.lazy(() => {
return import(/* webpackPrefetch: true */ './Viewport/OHIFCornerstoneViewport');
Expand Down Expand Up @@ -140,5 +141,6 @@ export {
CornerstoneExtensionTypes as Types,
toolNames,
getActiveViewportEnabledElement,
ImageOverlayViewerTool,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just exposes the tool externally to be used. Otherwise it becomes difficult to add new metadata.

};
export default cornerstoneExtension;
53 changes: 38 additions & 15 deletions extensions/cornerstone/src/tools/ImageOverlayViewerTool.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { VolumeViewport, metaData } from '@cornerstonejs/core';
import { utilities } from '@cornerstonejs/core';
import { VolumeViewport, metaData, utilities } from '@cornerstonejs/core';
import { IStackViewport, IVolumeViewport, Point3 } from '@cornerstonejs/core/dist/esm/types';
import { AnnotationDisplayTool, drawing } from '@cornerstonejs/tools';
import { guid } from '@ohif/core/src/utils';
Expand All @@ -15,6 +14,9 @@ interface CachedStat {
}[];
}

const _cachedOverlayMetadata: Map<string, any[]> = new Map();
let _cachedStats: { [key: string]: CachedStat } = {};

/**
* Image Overlay Viewer tool is not a traditional tool that requires user interactin.
* But it is used to display Pixel Overlays. And it will provide toggling capability.
Expand All @@ -27,8 +29,26 @@ interface CachedStat {
*/
class ImageOverlayViewerTool extends AnnotationDisplayTool {
static toolName = 'ImageOverlayViewer';
private _cachedOverlayMetadata: Map<string, any[]> = new Map();
private _cachedStats: { [key: string]: CachedStat } = {};
/** Adds the metadata for overlayPlaneModule */
public static add(imageId, metadata) {
if (_cachedOverlayMetadata.get(imageId) === metadata) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make the cache a standard metaData provider.

// This is a no-op here as the tool re-caches the data
return;
}
_cachedOverlayMetadata.set(imageId, metadata);
delete _cachedStats[imageId];
}

/** Standard getter for metadata */
public static get(type: string, query: string | string[]) {
if (Array.isArray(query)) {
return;
}
if (type !== 'overlayPlaneModule') {
return;
}
return _cachedOverlayMetadata.get(query);
}

wayfarer3130 marked this conversation as resolved.
Show resolved Hide resolved
constructor(
toolProps = {},
Expand All @@ -43,8 +63,8 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
}

onSetToolDisabled = (): void => {
this._cachedStats = {};
this._cachedOverlayMetadata = new Map();
_cachedStats = {};
_cachedOverlayMetadata.clear();
};

protected getReferencedImageId(viewport: IStackViewport | IVolumeViewport): string {
Expand All @@ -64,9 +84,8 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
return;
}

const overlays =
this._cachedOverlayMetadata.get(imageId) ??
metaData.get('overlayPlaneModule', imageId)?.overlays;
const overlayMetadata = metaData.get('overlayPlaneModule', imageId);
const overlays = overlayMetadata?.overlays;

// no overlays
if (!overlays?.length) {
Expand All @@ -79,7 +98,8 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
overlay.y ||= 0;
});

this._cachedOverlayMetadata.set(imageId, overlays);
// Will clear cached stat data when the overlay data changes
ImageOverlayViewerTool.add(imageId, overlayMetadata);

this._getCachedStat(imageId, overlays, this.configuration.fillColor).then(cachedStat => {
cachedStat.overlays.forEach(overlay => {
Expand Down Expand Up @@ -155,8 +175,8 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
overlayMetadata: any[],
color: number[]
): Promise<CachedStat> {
if (this._cachedStats[imageId] && this._isSameColor(this._cachedStats[imageId].color, color)) {
return this._cachedStats[imageId];
if (_cachedStats[imageId] && this._isSameColor(_cachedStats[imageId].color, color)) {
return _cachedStats[imageId];
}

const overlays = await Promise.all(
Expand All @@ -178,7 +198,7 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {

const dataUrl = this._renderOverlayToDataUrl(
{ width: overlay.columns, height: overlay.rows },
color,
overlay.color || color,
pixelData
);

Expand All @@ -191,12 +211,12 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
})
);

this._cachedStats[imageId] = {
_cachedStats[imageId] = {
color: color,
overlays: overlays.filter(overlay => overlay),
};

return this._cachedStats[imageId];
return _cachedStats[imageId];
}

/**
Expand Down Expand Up @@ -262,4 +282,7 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
}
}

// Needs to be higher priority than default provider
metaData.addProvider(ImageOverlayViewerTool.get, 10_000);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

register the provider for use.


export default ImageOverlayViewerTool;
Loading