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(handler): Add handler for unsupported sopclassUIDs #3601

Merged
merged 8 commits into from
Aug 16, 2023
38 changes: 20 additions & 18 deletions extensions/default/src/Panels/PanelStudyBrowser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ function PanelStudyBrowser({
const imageId = imageIds[Math.floor(imageIds.length / 2)];

// TODO: Is it okay that imageIds are not returned here for SR displaySets?
if (imageId) {
if (imageId && !displaySet?.unsupported) {
// When the image arrives, render it and store the result in the thumbnailImgSrcMap
newImageSrcEntry[dSet.displaySetInstanceUID] = await getImageSrc(
imageId
Expand Down Expand Up @@ -175,20 +175,22 @@ function PanelStudyBrowser({
const displaySet = displaySetService.getDisplaySetByUID(
dSet.displaySetInstanceUID
);
const imageIds = dataSource.getImageIdsForDisplaySet(displaySet);
const imageId = imageIds[Math.floor(imageIds.length / 2)];

// TODO: Is it okay that imageIds are not returned here for SR displaysets?
if (imageId) {
// When the image arrives, render it and store the result in the thumbnailImgSrcMap
newImageSrcEntry[dSet.displaySetInstanceUID] = await getImageSrc(
imageId,
dSet.initialViewport
);
if (isMounted.current) {
setThumbnailImageSrcMap(prevState => {
return { ...prevState, ...newImageSrcEntry };
});
if (!displaySet?.unsupported) {
const imageIds = dataSource.getImageIdsForDisplaySet(displaySet);
const imageId = imageIds[Math.floor(imageIds.length / 2)];

// TODO: Is it okay that imageIds are not returned here for SR displaysets?
if (imageId) {
// When the image arrives, render it and store the result in the thumbnailImgSrcMap
newImageSrcEntry[dSet.displaySetInstanceUID] = await getImageSrc(
imageId,
dSet.initialViewport
);
if (isMounted.current) {
setThumbnailImageSrcMap(prevState => {
return { ...prevState, ...newImageSrcEntry };
});
}
}
}
});
Expand Down Expand Up @@ -308,7 +310,7 @@ function _mapDisplaySets(displaySets, thumbnailImageSrcMap) {
.filter(ds => !ds.excludeFromThumbnailBrowser)
.forEach(ds => {
const imageSrc = thumbnailImageSrcMap[ds.displaySetInstanceUID];
const componentType = _getComponentType(ds.Modality);
const componentType = _getComponentType(ds);

const array =
componentType === 'thumbnail'
Expand Down Expand Up @@ -348,8 +350,8 @@ const thumbnailNoImageModalities = [
'RTDOSE',
];

function _getComponentType(Modality) {
if (thumbnailNoImageModalities.includes(Modality)) {
function _getComponentType(ds) {
if (thumbnailNoImageModalities.includes(ds.Modality) || ds?.unsupported) {
// TODO probably others.
return 'thumbnailNoImage';
}
Expand Down
30 changes: 30 additions & 0 deletions extensions/default/src/getDisplaySetsFromUnsupportedSeries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import ImageSet from '@ohif/core/src/classes/ImageSet';
import { DisplaySetMessage, DisplaySetMessageList } from '@ohif/core';
/**
* Default handler for a instance list with an unsupported sopClassUID
*/
export default function getDisplaySetsFromUnsupportedSeries(instances) {
const imageSet = new ImageSet(instances);
const messages = new DisplaySetMessageList();
messages.addMessage(DisplaySetMessage.CODES.UNSUPPORTED_DISPLAYSET);
const instance = instances[0];

imageSet.setAttributes({
displaySetInstanceUID: imageSet.uid, // create a local alias for the imageSet UID
SeriesDate: instance.SeriesDate,
SeriesTime: instance.SeriesTime,
SeriesInstanceUID: instance.SeriesInstanceUID,
StudyInstanceUID: instance.StudyInstanceUID,
SeriesNumber: instance.SeriesNumber || 0,
FrameRate: instance.FrameTime,
SOPClassUID: instance.SOPClassUID,
SeriesDescription: instance.SeriesDescription || '',
Modality: instance.Modality,
numImageFrames: instances.length,
unsupported: true,
SOPClassHandlerId: 'unsupported',
isReconstructable: false,
messages,
});
return [imageSet];
}
6 changes: 6 additions & 0 deletions extensions/default/src/getSopClassHandlerModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ImageSet from '@ohif/core/src/classes/ImageSet';
import isDisplaySetReconstructable from '@ohif/core/src/utils/isDisplaySetReconstructable';
import { id } from './id';
import getDisplaySetMessages from './getDisplaySetMessages';
import getDisplaySetsFromUnsupportedSeries from './getDisplaySetsFromUnsupportedSeries';

const sopClassHandlerName = 'stack';

Expand Down Expand Up @@ -213,6 +214,11 @@ function getSopClassHandlerModule() {
sopClassUids,
getDisplaySetsFromSeries,
},
{
name: 'not-supported-display-sets-handler',
sopClassUids: [],
getDisplaySetsFromSeries: getDisplaySetsFromUnsupportedSeries,
},
];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ function PanelStudyBrowserTracking({
const imageId = imageIds[Math.floor(imageIds.length / 2)];

// TODO: Is it okay that imageIds are not returned here for SR displaysets?
if (imageId) {
if (imageId && !displaySet?.unsupported) {
rodrigobasilio2022 marked this conversation as resolved.
Show resolved Hide resolved
// When the image arrives, render it and store the result in the thumbnailImgSrcMap
newImageSrcEntry[dSet.displaySetInstanceUID] = await getImageSrc(
imageId
Expand Down Expand Up @@ -212,23 +212,24 @@ function PanelStudyBrowserTracking({
const displaySet = displaySetService.getDisplaySetByUID(
displaySetInstanceUID
);

if (options.madeInClient) {
setJumpToDisplaySet(displaySetInstanceUID);
}

const imageIds = dataSource.getImageIdsForDisplaySet(displaySet);
const imageId = imageIds[Math.floor(imageIds.length / 2)];

// TODO: Is it okay that imageIds are not returned here for SR displaysets?
if (imageId) {
// When the image arrives, render it and store the result in the thumbnailImgSrcMap
newImageSrcEntry[displaySetInstanceUID] = await getImageSrc(
imageId
);
setThumbnailImageSrcMap(prevState => {
return { ...prevState, ...newImageSrcEntry };
});
if (!displaySet?.unsupported) {
if (options.madeInClient) {
setJumpToDisplaySet(displaySetInstanceUID);
}

const imageIds = dataSource.getImageIdsForDisplaySet(displaySet);
const imageId = imageIds[Math.floor(imageIds.length / 2)];

// TODO: Is it okay that imageIds are not returned here for SR displaysets?
if (imageId) {
// When the image arrives, render it and store the result in the thumbnailImgSrcMap
newImageSrcEntry[displaySetInstanceUID] = await getImageSrc(
imageId
);
setThumbnailImageSrcMap(prevState => {
return { ...prevState, ...newImageSrcEntry };
});
}
}
});
}
Expand Down Expand Up @@ -424,7 +425,7 @@ function _mapDisplaySets(
.filter(ds => !ds.excludeFromThumbnailBrowser)
.forEach(ds => {
const imageSrc = thumbnailImageSrcMap[ds.displaySetInstanceUID];
const componentType = _getComponentType(ds.Modality);
const componentType = _getComponentType(ds);
const numPanes = viewportGridService.getNumViewportPanes();
const viewportIdentificator =
numPanes === 1
Expand Down Expand Up @@ -471,7 +472,7 @@ function _mapDisplaySets(

if (componentType === 'thumbnailNoImage') {
if (dataSource.reject && dataSource.reject.series) {
thumbnailProps.canReject = true;
thumbnailProps.canReject = !ds?.unsupported;
thumbnailProps.onReject = () => {
uiDialogService.create({
id: 'ds-reject-sr',
Expand Down Expand Up @@ -564,8 +565,8 @@ const thumbnailNoImageModalities = [
'OT',
];

function _getComponentType(Modality) {
if (thumbnailNoImageModalities.includes(Modality)) {
function _getComponentType(ds) {
if (thumbnailNoImageModalities.includes(ds.Modality) || ds?.unsupported) {
return 'thumbnailNoImage';
}

Expand Down
4 changes: 4 additions & 0 deletions platform/app/src/components/ViewportGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ function ViewerViewportGrid(props) {
displaySetService.getDisplaySetByUID(displaySetInstanceUID) || {}
);
}
).filter(
(displaySet) => {
return !displaySet?.unsupported;
}
);

const ViewportComponent = _getViewportComponent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class DisplaySetMessage {
INCONSISTENT_COMPONENTS: 10,
INCONSISTENT_ORIENTATIONS: 11,
INCONSISTENT_POSITION_INFORMATION: 12,
UNSUPPORTED_DISPLAYSET: 13,
};

constructor(id: number) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type DisplaySet = {
StudyInstanceUID: string;
SeriesInstanceUID?: string;
numImages?: number;
unsupported?: boolean;
};

const displaySetCache = new Map<string, DisplaySet>();
Expand Down Expand Up @@ -48,6 +49,7 @@ export default class DisplaySetService extends PubSubService {
};

public activeDisplaySets = [];
public unsuportedSOPClassHandler;
extensionManager: ExtensionManager;

protected activeDisplaySetsMap = new Map<string, DisplaySet>();
Expand All @@ -58,6 +60,8 @@ export default class DisplaySetService extends PubSubService {

constructor() {
super(EVENTS);
this.unsuportedSOPClassHandler =
'@ohif/extension-default.sopClassHandlerModule.not-supported-display-sets-handler';
}

public init(extensionManager, SOPClassHandlerIds): void {
Expand Down Expand Up @@ -85,6 +89,14 @@ export default class DisplaySetService extends PubSubService {
});
}

/**
* Sets the handler for unsupported sop classes
* @param sopClassHandlerUID
*/
public setUnsuportedSOPClassHandler(sopClassHandler) {
this.unsuportedSOPClassHandler = sopClassHandler;
}

/**
* Adds new display sets directly, as specified.
* Use this function when the display sets are created externally directly
Expand Down Expand Up @@ -256,6 +268,47 @@ export default class DisplaySetService extends PubSubService {
this.activeDisplaySetsMap.clear();
}

/**
* This function hides the old makeDisplaySetForInstances function to first
* separate the instances by sopClassUID so each call have only instances
* with the same sopClassUID, to avoid a series composed by different
* sopClassUIDs be filtered inside one of the SOPClassHandler functions and
* didn't appear in the series list.
* @param instancesSrc
* @param settings
* @returns
*/
public makeDisplaySetForInstances(
instancesSrc: InstanceMetadata[],
settings
): DisplaySet[] {
// creating a sopClassUID list and for each sopClass associate its respective
// instance list
const instancesForSetSOPClasses = instancesSrc.reduce(
(sopClassList, instance) => {
if (!(instance.SOPClassUID in sopClassList)) {
sopClassList[instance.SOPClassUID] = [];
}
sopClassList[instance.SOPClassUID].push(instance);
return sopClassList;
},
{}
);
// for each sopClassUID, call the old makeDisplaySetForInstances with a
// instance list composed only by instances with the same sopClassUID and
// accumulate the displaySets in the variable allDisplaySets
const sopClasses = Object.keys(instancesForSetSOPClasses);
let allDisplaySets = [];
sopClasses.forEach(sopClass => {
const displaySets = this._makeDisplaySetForInstances(
instancesForSetSOPClasses[sopClass],
settings
);
allDisplaySets = [...allDisplaySets, ...displaySets];
});
return allDisplaySets;
}

/**
* Creates new display sets for the instances contained in instancesSrc
* according to the sop class handlers registered.
Expand All @@ -272,7 +325,7 @@ export default class DisplaySetService extends PubSubService {
* @param settings are settings to add
* @returns Array of the display sets added.
*/
public makeDisplaySetForInstances(
private _makeDisplaySetForInstances(
sedghi marked this conversation as resolved.
Show resolved Hide resolved
instancesSrc: InstanceMetadata[],
settings
): DisplaySet[] {
Expand Down Expand Up @@ -355,6 +408,26 @@ export default class DisplaySetService extends PubSubService {
allDisplaySets.push(...displaySets);
}
}
// applying the default sopClassUID handler
if (allDisplaySets.length === 0) {
// applying hp-defined viewport settings to the displaysets
const handler = this.extensionManager.getModuleEntry(
this.unsuportedSOPClassHandler
);
const displaySets = handler.getDisplaySetsFromSeries(instances);
if (displaySets?.length) {
displaySets.forEach(ds => {
Object.keys(settings).forEach(key => {
ds[key] = settings[key];
});
});

this._addDisplaySetsToCache(displaySets);
this._addActiveDisplaySets(displaySets);

allDisplaySets.push(...displaySets);
}
}
return allDisplaySets;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ interface IDisplaySet {
StudyInstanceUID: string;
SeriesInstanceUID?: string;
SeriesNumber?: string;
unsupported?: boolean;
}

export default IDisplaySet;
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,13 @@ export default class HangingProtocolService extends PubSubService {
}

getViewportsRequireUpdate(viewportIndex, displaySetInstanceUID) {
const { displaySetService } = this._servicesManager.services;
const displaySet = displaySetService.getDisplaySetByUID(
displaySetInstanceUID
);
if (displaySet?.unsupported) {
throw new Error('Unsupported displaySet');
}
rodrigobasilio2022 marked this conversation as resolved.
Show resolved Hide resolved
const newDisplaySetInstanceUID = displaySetInstanceUID;
const protocol = this.protocol;
const protocolStage = protocol.stages[this.stageIndex];
Expand Down Expand Up @@ -1428,7 +1435,7 @@ export default class HangingProtocolService extends PubSubService {
}

const studyDisplaySets = this.displaySets.filter(
it => it.StudyInstanceUID === study.StudyInstanceUID
it => it.StudyInstanceUID === study.StudyInstanceUID && !it?.unsupported
);

const studyMatchDetails = this.protocolEngine.findMatch(
Expand Down
3 changes: 2 additions & 1 deletion platform/i18n/src/locales/en-US/Messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
"9": "DisplaySet has inconsistent dimensions between frames.",
"10": "DisplaySet has frames with inconsistent number of components.",
"11": "DisplaySet has frames with inconsistent orientations.",
"12": "DisplaySet has inconsistent position information."
"12": "DisplaySet has inconsistent position information.",
"13": "Unsupported displaySet."
}
3 changes: 2 additions & 1 deletion platform/i18n/src/locales/pt-BR/Messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
"9": "Série possui dimensões inconsistentes entre frames.",
"10": "Série possui frames com componentes inconsistentes.",
"11": "Série possui frames com orientações inconsistentes.",
"12": "Série possui informação de posição inconsistentes."
"12": "Série possui informação de posição inconsistentes.",
"13": "Série não suportada."
}
Loading