feat: Update approach to better handle rtdose instead of disabling panel

Co-authored-by: Davide Punzo <punzodavide@hotmail.it>
This commit is contained in:
Igor Octaviano 2020-12-03 13:36:02 -03:00 committed by GitHub
parent fe03fc6f55
commit f3cecf129b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 105 additions and 93 deletions

View File

@ -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>
); );
}; };

View File

@ -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,

View File

@ -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;