feat: Update approach to better handle rtdose instead of disabling panel
Co-authored-by: Davide Punzo <punzodavide@hotmail.it>
This commit is contained in:
parent
fe03fc6f55
commit
f3cecf129b
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import cornerstoneTools from 'cornerstone-tools';
|
import cornerstoneTools from 'cornerstone-tools';
|
||||||
import cornerstone from 'cornerstone-core';
|
import cornerstone from 'cornerstone-core';
|
||||||
@ -31,19 +31,20 @@ const refreshViewport = () => {
|
|||||||
*
|
*
|
||||||
* @param {Object} props
|
* @param {Object} props
|
||||||
* @param {Array} props.studies
|
* @param {Array} props.studies
|
||||||
* @param {Array} props.viewports - viewportSpecificData
|
* @param {Array} props.getActiveViewport - get active viewport data
|
||||||
* @param {number} props.activeIndex - activeViewportIndex
|
* @param {number} props.activeIndex - activeViewportIndex
|
||||||
* @param {number} props.isOpen - isOpen
|
* @param {number} props.isOpen - isOpen
|
||||||
* @returns component
|
* @returns component
|
||||||
*/
|
*/
|
||||||
const RTPanel = ({
|
const RTPanel = ({
|
||||||
studies,
|
studies,
|
||||||
viewports,
|
|
||||||
activeIndex,
|
activeIndex,
|
||||||
isOpen,
|
isOpen,
|
||||||
onContourItemClick,
|
onContourItemClick,
|
||||||
activeContexts = [],
|
activeContexts = [],
|
||||||
contexts = {},
|
contexts = {},
|
||||||
|
activeViewport,
|
||||||
|
getActiveViewport
|
||||||
}) => {
|
}) => {
|
||||||
const isVTK = () => activeContexts.includes(contexts.VTK);
|
const isVTK = () => activeContexts.includes(contexts.VTK);
|
||||||
const isCornerstone = () => activeContexts.includes(contexts.CORNERSTONE);
|
const isCornerstone = () => activeContexts.includes(contexts.CORNERSTONE);
|
||||||
@ -54,11 +55,11 @@ const RTPanel = ({
|
|||||||
referencedDisplaysets: [],
|
referencedDisplaysets: [],
|
||||||
sets: [],
|
sets: [],
|
||||||
selectedSet: null,
|
selectedSet: null,
|
||||||
|
isLocked: false
|
||||||
};
|
};
|
||||||
|
|
||||||
const [state, setState] = useState(DEFAULT_STATE);
|
const [state, setState] = useState(DEFAULT_STATE);
|
||||||
const [showSettings, setShowSettings] = useState(false);
|
const [showSettings, setShowSettings] = useState(false);
|
||||||
const activeViewport = viewports[activeIndex];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: Improve the way we notify parts of the app that depends on rts to be loaded.
|
* TODO: Improve the way we notify parts of the app that depends on rts to be loaded.
|
||||||
@ -81,27 +82,32 @@ const RTPanel = ({
|
|||||||
document.addEventListener('extensiondicomrtrtloaded', updateStructureSets);
|
document.addEventListener('extensiondicomrtrtloaded', updateStructureSets);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener(
|
document.removeEventListener('extensiondicomrtrtloaded', updateStructureSets);
|
||||||
'extensiondicomrtrtloaded',
|
|
||||||
updateStructureSets
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const studyMetadata = studyMetadataManager.get(activeViewport.StudyInstanceUID);
|
||||||
|
const referencedDisplaysets = studyMetadata.getDerivedDatasets({
|
||||||
|
referencedSeriesInstanceUID: activeViewport.SeriesInstanceUID,
|
||||||
|
Modality: 'RTSTRUCT',
|
||||||
|
});
|
||||||
|
setState(state => ({ ...state, isLocked: !referencedDisplaysets.length }));
|
||||||
|
}, [activeViewport]);
|
||||||
|
|
||||||
const updateStructureSets = () => {
|
const updateStructureSets = () => {
|
||||||
|
const viewport = getActiveViewport();
|
||||||
const module = cornerstoneTools.getModule('rtstruct');
|
const module = cornerstoneTools.getModule('rtstruct');
|
||||||
const StructureSets = module.state.StructureSets;
|
const StructureSets = module.state.StructureSets;
|
||||||
|
|
||||||
if (StructureSets && StructureSets.length) {
|
if (StructureSets && StructureSets.length) {
|
||||||
const viewportSets = module.getters.structuresSetsWhichReferenceSeriesInstanceUid(
|
const viewportSets = module.getters.structuresSetsWhichReferenceSeriesInstanceUid(
|
||||||
activeViewport.SeriesInstanceUID
|
viewport.SeriesInstanceUID
|
||||||
);
|
);
|
||||||
|
|
||||||
const studyMetadata = studyMetadataManager.get(
|
const studyMetadata = studyMetadataManager.get(viewport.StudyInstanceUID);
|
||||||
activeViewport.StudyInstanceUID
|
|
||||||
);
|
|
||||||
const referencedDisplaysets = studyMetadata.getDerivedDatasets({
|
const referencedDisplaysets = studyMetadata.getDerivedDatasets({
|
||||||
referencedSeriesInstanceUID: activeViewport.SeriesInstanceUID,
|
referencedSeriesInstanceUID: viewport.SeriesInstanceUID,
|
||||||
Modality: 'RTSTRUCT',
|
Modality: 'RTSTRUCT',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -118,10 +124,6 @@ const RTPanel = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
updateStructureSets();
|
|
||||||
}, [studies, viewports, activeIndex]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setShowSettings(showSettings && !isOpen);
|
setShowSettings(showSettings && !isOpen);
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
@ -232,78 +234,80 @@ const RTPanel = ({
|
|||||||
<div className="dcmrt-panel">
|
<div className="dcmrt-panel">
|
||||||
<div className="dcmrt-panel-header">
|
<div className="dcmrt-panel-header">
|
||||||
<h3>RT Structure Sets</h3>
|
<h3>RT Structure Sets</h3>
|
||||||
<Icon
|
{!state.isLocked && (
|
||||||
className="cog-icon"
|
<Icon
|
||||||
name="cog"
|
className="cog-icon"
|
||||||
width="25px"
|
name="cog"
|
||||||
height="25px"
|
width="25px"
|
||||||
onClick={() => setShowSettings(true)}
|
height="25px"
|
||||||
/>
|
onClick={() => setShowSettings(true)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!state.referencedDisplaysets.length && (
|
{!state.isLocked && !state.referencedDisplaysets.length && <LoadingIndicator expand height="70px" width="70px" />}
|
||||||
<LoadingIndicator expand height="70px" width="70px" />
|
{state.sets && state.referencedDisplaysets.map(displaySet => {
|
||||||
)}
|
const { SeriesInstanceUID, metadata, isLoaded } = displaySet;
|
||||||
{state.sets &&
|
|
||||||
state.referencedDisplaysets.map(displaySet => {
|
|
||||||
const { SeriesInstanceUID, metadata, isLoaded } = displaySet;
|
|
||||||
|
|
||||||
const module = cornerstoneTools.getModule('rtstruct');
|
const module = cornerstoneTools.getModule('rtstruct');
|
||||||
const sets = module.getters.structuresSetsWhichReferenceSeriesInstanceUid(
|
const sets = module.getters.structuresSetsWhichReferenceSeriesInstanceUid(
|
||||||
viewports[activeIndex].SeriesInstanceUID
|
activeViewport.SeriesInstanceUID
|
||||||
);
|
);
|
||||||
|
|
||||||
const loadedSet = sets.find(
|
const loadedSet = sets.find(
|
||||||
set => set.SeriesInstanceUID === SeriesInstanceUID
|
set => set.SeriesInstanceUID === SeriesInstanceUID
|
||||||
);
|
);
|
||||||
return (
|
|
||||||
<PanelSection
|
if (!loadedSet) return null;
|
||||||
key={SeriesInstanceUID}
|
|
||||||
title={metadata.StructureSetLabel}
|
return (
|
||||||
loading={!isLoaded || !loadedSet}
|
<PanelSection
|
||||||
visible={isLoaded && loadedSet && loadedSet.visible}
|
key={SeriesInstanceUID}
|
||||||
hideVisibleButton={!isLoaded}
|
title={metadata.StructureSetLabel}
|
||||||
expanded={
|
loading={!isLoaded || !loadedSet}
|
||||||
isLoaded &&
|
visible={isLoaded && loadedSet && loadedSet.visible}
|
||||||
loadedSet.SeriesInstanceUID ===
|
hideVisibleButton={!isLoaded}
|
||||||
state.selectedSet.SeriesInstanceUID
|
expanded={
|
||||||
|
isLoaded &&
|
||||||
|
loadedSet.SeriesInstanceUID ===
|
||||||
|
state.selectedSet.SeriesInstanceUID
|
||||||
|
}
|
||||||
|
onVisibilityChange={newVisibility => {
|
||||||
|
const module = cornerstoneTools.getModule('rtstruct');
|
||||||
|
|
||||||
|
if (newVisibility) {
|
||||||
|
module.setters.showStructureSet(loadedSet.SeriesInstanceUID);
|
||||||
|
} else {
|
||||||
|
module.setters.hideStructureSet(loadedSet.SeriesInstanceUID);
|
||||||
}
|
}
|
||||||
onVisibilityChange={newVisibility => {
|
const sets = module.getters.structuresSetsWhichReferenceSeriesInstanceUid(
|
||||||
|
activeViewport.SeriesInstanceUID
|
||||||
|
);
|
||||||
|
setState(state => ({ ...state, sets }));
|
||||||
|
refreshViewport();
|
||||||
|
}}
|
||||||
|
onExpandChange={async () => {
|
||||||
|
if (!isLoaded) {
|
||||||
|
await displaySet.load(activeViewport, studies);
|
||||||
const module = cornerstoneTools.getModule('rtstruct');
|
const module = cornerstoneTools.getModule('rtstruct');
|
||||||
|
|
||||||
if (newVisibility) {
|
|
||||||
module.setters.showStructureSet(loadedSet.SeriesInstanceUID);
|
|
||||||
} else {
|
|
||||||
module.setters.hideStructureSet(loadedSet.SeriesInstanceUID);
|
|
||||||
}
|
|
||||||
const sets = module.getters.structuresSetsWhichReferenceSeriesInstanceUid(
|
const sets = module.getters.structuresSetsWhichReferenceSeriesInstanceUid(
|
||||||
viewports[activeIndex].SeriesInstanceUID
|
activeViewport.SeriesInstanceUID
|
||||||
);
|
);
|
||||||
setState(state => ({ ...state, sets }));
|
const selectedSet = sets.find(
|
||||||
refreshViewport();
|
set => set.SeriesInstanceUID === SeriesInstanceUID
|
||||||
}}
|
);
|
||||||
onExpandChange={async () => {
|
setState(state => ({ ...state, selectedSet, sets }));
|
||||||
if (!isLoaded) {
|
}
|
||||||
await displaySet.load(viewports[activeIndex], studies);
|
}}
|
||||||
const module = cornerstoneTools.getModule('rtstruct');
|
>
|
||||||
const sets = module.getters.structuresSetsWhichReferenceSeriesInstanceUid(
|
<ScrollableArea>
|
||||||
viewports[activeIndex].SeriesInstanceUID
|
<TableList headless>
|
||||||
);
|
{isLoaded &&
|
||||||
const selectedSet = sets.find(
|
loadedSet.ROIContours.map(c => toContourItem(c, loadedSet))}
|
||||||
set => set.SeriesInstanceUID === SeriesInstanceUID
|
</TableList>
|
||||||
);
|
</ScrollableArea>
|
||||||
setState(state => ({ ...state, selectedSet, sets }));
|
</PanelSection>
|
||||||
}
|
);
|
||||||
}}
|
})}
|
||||||
>
|
|
||||||
<ScrollableArea>
|
|
||||||
<TableList headless>
|
|
||||||
{isLoaded &&
|
|
||||||
loadedSet.ROIContours.map(c => toContourItem(c, loadedSet))}
|
|
||||||
</TableList>
|
|
||||||
</ScrollableArea>
|
|
||||||
</PanelSection>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -90,11 +90,11 @@ export default async function loadRTStruct(
|
|||||||
const sopInstanceUID = ContourImageSequence
|
const sopInstanceUID = ContourImageSequence
|
||||||
? ContourImageSequence.ReferencedSOPInstanceUID
|
? ContourImageSequence.ReferencedSOPInstanceUID
|
||||||
: _getClosestSOPInstanceUID(
|
: _getClosestSOPInstanceUID(
|
||||||
ContourData,
|
ContourData,
|
||||||
ContourGeometricType,
|
ContourGeometricType,
|
||||||
NumberOfContourPoints,
|
NumberOfContourPoints,
|
||||||
imageIdSopInstanceUidPairs
|
imageIdSopInstanceUidPairs
|
||||||
);
|
);
|
||||||
const imageId = _getImageId(imageIdSopInstanceUidPairs, sopInstanceUID);
|
const imageId = _getImageId(imageIdSopInstanceUidPairs, sopInstanceUID);
|
||||||
const imageIdSpecificToolData = _getOrCreateImageIdSpecificToolData(
|
const imageIdSpecificToolData = _getOrCreateImageIdSpecificToolData(
|
||||||
toolState,
|
toolState,
|
||||||
|
|||||||
@ -83,6 +83,8 @@ class Viewer extends Component {
|
|||||||
disassociate: this.disassociateStudy,
|
disassociate: this.disassociateStudy,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._getActiveViewport = this._getActiveViewport.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -214,6 +216,10 @@ class Viewer extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_getActiveViewport() {
|
||||||
|
return this.props.viewports[this.props.activeViewportIndex];
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let VisiblePanelLeft, VisiblePanelRight;
|
let VisiblePanelLeft, VisiblePanelRight;
|
||||||
const panelExtensions = extensionManager.modules[MODULE_TYPES.PANEL];
|
const panelExtensions = extensionManager.modules[MODULE_TYPES.PANEL];
|
||||||
@ -314,11 +320,11 @@ class Viewer extends Component {
|
|||||||
activeIndex={this.props.activeViewportIndex}
|
activeIndex={this.props.activeViewportIndex}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ConnectedStudyBrowser
|
<ConnectedStudyBrowser
|
||||||
studies={this.state.thumbnails}
|
studies={this.state.thumbnails}
|
||||||
studyMetadata={this.props.studies}
|
studyMetadata={this.props.studies}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</SidePanel>
|
</SidePanel>
|
||||||
</ErrorBoundaryDialog>
|
</ErrorBoundaryDialog>
|
||||||
|
|
||||||
@ -341,6 +347,8 @@ class Viewer extends Component {
|
|||||||
viewports={this.props.viewports}
|
viewports={this.props.viewports}
|
||||||
studies={this.props.studies}
|
studies={this.props.studies}
|
||||||
activeIndex={this.props.activeViewportIndex}
|
activeIndex={this.props.activeViewportIndex}
|
||||||
|
activeViewport={this.props.viewports[this.props.activeViewportIndex]}
|
||||||
|
getActiveViewport={this._getActiveViewport}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</SidePanel>
|
</SidePanel>
|
||||||
@ -363,7 +371,7 @@ export default withDialog(Viewer);
|
|||||||
* @param {Study[]} studies
|
* @param {Study[]} studies
|
||||||
* @param {DisplaySet[]} studies[].displaySets
|
* @param {DisplaySet[]} studies[].displaySets
|
||||||
*/
|
*/
|
||||||
const _mapStudiesToThumbnails = function(studies) {
|
const _mapStudiesToThumbnails = function (studies) {
|
||||||
return studies.map(study => {
|
return studies.map(study => {
|
||||||
const { StudyInstanceUID } = study;
|
const { StudyInstanceUID } = study;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user