feat(handler): Add handler for unsupported sopclassUIDs (#3601)
This commit is contained in:
1 parent
de6976df3b
commit
f845f87716
16 files changed
+180
-64
No files matched your search
@@ -280,6 +280,10 @@ function ViewerViewportGrid(props) {
|
||||
displaySetService.getDisplaySetByUID(displaySetInstanceUID) || {}
|
||||
);
|
||||
}
|
||||
).filter(
|
||||
(displaySet) => {
|
||||
return !displaySet?.unsupported;
|
||||
}
|
||||
);
|
||||
|
||||
const ViewportComponent = _getViewportComponent(
|
||||
|
||||
@@ -16,6 +16,7 @@ class DisplaySetMessage {
|
||||
INCONSISTENT_COMPONENTS: 10,
|
||||
INCONSISTENT_ORIENTATIONS: 11,
|
||||
INCONSISTENT_POSITION_INFORMATION: 12,
|
||||
UNSUPPORTED_DISPLAYSET: 13,
|
||||
};
|
||||
|
||||
constructor(id: number) {
|
||||
|
||||
@@ -9,6 +9,7 @@ export type DisplaySet = {
|
||||
StudyInstanceUID: string;
|
||||
SeriesInstanceUID?: string;
|
||||
numImages?: number;
|
||||
unsupported?: boolean;
|
||||
};
|
||||
|
||||
const displaySetCache = new Map<string, DisplaySet>();
|
||||
@@ -48,6 +49,7 @@ export default class DisplaySetService extends PubSubService {
|
||||
};
|
||||
|
||||
public activeDisplaySets = [];
|
||||
public unsuportedSOPClassHandler;
|
||||
extensionManager: ExtensionManager;
|
||||
|
||||
protected activeDisplaySetsMap = new Map<string, DisplaySet>();
|
||||
@@ -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 {
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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(
|
||||
instancesSrc: InstanceMetadata[],
|
||||
settings
|
||||
): DisplaySet[] {
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ interface IDisplaySet {
|
||||
StudyInstanceUID: string;
|
||||
SeriesInstanceUID?: string;
|
||||
SeriesNumber?: string;
|
||||
unsupported?: boolean;
|
||||
}
|
||||
|
||||
export default IDisplaySet;
|
||||
@@ -559,6 +559,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');
|
||||
}
|
||||
const newDisplaySetInstanceUID = displaySetInstanceUID;
|
||||
const protocol = this.protocol;
|
||||
const protocolStage = protocol.stages[this.stageIndex];
|
||||
@@ -1431,7 +1438,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(
|
||||
|
||||
@@ -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."
|
||||
}
|
||||
@@ -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."
|
||||
}
|
||||
+3
-2
@@ -12,7 +12,7 @@ import { useTranslation } from 'react-i18next';
|
||||
const DisplaySetMessageListTooltip = ({ messages, id }): React.ReactNode => {
|
||||
const { t } = useTranslation('Messages');
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
if (messages.size()) {
|
||||
if (messages?.size()) {
|
||||
return (
|
||||
<>
|
||||
<Icon
|
||||
@@ -29,7 +29,7 @@ const DisplaySetMessageListTooltip = ({ messages, id }): React.ReactNode => {
|
||||
arrow="center"
|
||||
parent={`#${id}`}
|
||||
>
|
||||
<div className="bg-primary-dark border border-secondary-light text-white text-base rounded text-left max-w-40">
|
||||
<div className="bg-primary-dark border border-secondary-light text-white text-base rounded text-left max-w-64">
|
||||
<div
|
||||
className="break-normal text-base text-blue-300 font-bold"
|
||||
style={{
|
||||
@@ -42,6 +42,7 @@ const DisplaySetMessageListTooltip = ({ messages, id }): React.ReactNode => {
|
||||
<ol
|
||||
style={{
|
||||
marginLeft: '12px',
|
||||
marginRight: '12px',
|
||||
}}
|
||||
>
|
||||
{messages.messages.map((message, index) => (
|
||||
|
||||
@@ -82,7 +82,7 @@ const Thumbnail = ({
|
||||
</div>
|
||||
<DisplaySetMessageListTooltip
|
||||
messages={messages}
|
||||
id={`display-set-tooltip-${seriesNumber}`}
|
||||
id={`display-set-tooltip-${displaySetInstanceUID}`}
|
||||
/>
|
||||
</div>
|
||||
<div className="text-base text-white break-all">{description}</div>
|
||||
|
||||
@@ -159,7 +159,7 @@ function _getModalityTooltip(modality) {
|
||||
const _modalityTooltips = {
|
||||
SR: 'Structured Report',
|
||||
SEG: 'Segmentation',
|
||||
RT: 'RT Structure Set',
|
||||
RTSTRUCT: 'RT Structure Set',
|
||||
};
|
||||
|
||||
export default ThumbnailList;
|
||||
@@ -5,6 +5,7 @@ import { useDrag } from 'react-dnd';
|
||||
import Icon from '../Icon';
|
||||
import Tooltip from '../Tooltip';
|
||||
import Typography from '../Typography';
|
||||
import DisplaySetMessageListTooltip from '../DisplaySetMessageListTooltip';
|
||||
|
||||
const ThumbnailNoImage = ({
|
||||
displaySetInstanceUID,
|
||||
@@ -57,23 +58,10 @@ const ThumbnailNoImage = ({
|
||||
</div>
|
||||
</Tooltip>
|
||||
<span className="ml-4 text-base text-blue-300">{seriesDate}</span>
|
||||
{messages?.size() ? (
|
||||
<div>
|
||||
<Tooltip
|
||||
position="left"
|
||||
tight={true}
|
||||
content={
|
||||
<div className="text-left max-w-40">
|
||||
{messages.thumbnailContents()}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Icon name="notifications-warning" className="w-3 h-3" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<DisplaySetMessageListTooltip
|
||||
messages={messages}
|
||||
id={`display-set-tooltip-${displaySetInstanceUID}`}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-row">
|
||||
{canReject && (
|
||||
@@ -107,7 +95,7 @@ ThumbnailNoImage.propTypes = {
|
||||
/** Must match the "type" a dropTarget expects */
|
||||
type: PropTypes.string.isRequired,
|
||||
}),
|
||||
description: PropTypes.string.isRequired,
|
||||
description: PropTypes.string,
|
||||
modality: PropTypes.string.isRequired,
|
||||
/* Tooltip message to display when modality text is hovered */
|
||||
modalityTooltip: PropTypes.string.isRequired,
|
||||
|
||||
@@ -198,7 +198,7 @@ ViewportActionBar.propTypes = {
|
||||
patientAge: PropTypes.string.isRequired,
|
||||
MRN: PropTypes.string.isRequired,
|
||||
thickness: PropTypes.string.isRequired,
|
||||
thicknessUnits: PropTypes.string.isRequired,
|
||||
thicknessUnits: PropTypes.string,
|
||||
spacing: PropTypes.string.isRequired,
|
||||
scanner: PropTypes.string.isRequired,
|
||||
}),
|
||||
|
||||
Reference in new issue
Block a user