From e0fb439e988ad653f9af42b7424fc30bb2c0d279 Mon Sep 17 00:00:00 2001 From: Davide Punzo Date: Mon, 12 Sep 2022 14:22:32 +0200 Subject: [PATCH] Fix IDC Re #2918: Runtime tolerance for SEGs loading (#2924) --- .../SegmentationPanel/SegmentationPanel.js | 27 +++++++++++ .../SegmentationSettings.js | 48 ++++++++++++++++--- .../src/getOHIFDicomSegSopClassHandler.js | 14 ++++-- extensions/dicom-segmentation/src/index.js | 1 + 4 files changed, 79 insertions(+), 11 deletions(-) diff --git a/extensions/dicom-segmentation/src/components/SegmentationPanel/SegmentationPanel.js b/extensions/dicom-segmentation/src/components/SegmentationPanel/SegmentationPanel.js index 324d05da3..256baf142 100644 --- a/extensions/dicom-segmentation/src/components/SegmentationPanel/SegmentationPanel.js +++ b/extensions/dicom-segmentation/src/components/SegmentationPanel/SegmentationPanel.js @@ -36,6 +36,7 @@ const { studyMetadataManager } = utils; * @param {Function} props.onConfigurationChange - Configuration change handler * @param {Function} props.activeContexts - List of active application contexts * @param {Function} props.contexts - List of available application contexts + * @param {Function} props.servicesManager - Services manager * @returns component */ const SegmentationPanel = ({ @@ -50,6 +51,7 @@ const SegmentationPanel = ({ onSelectedSegmentationChange, activeContexts = [], contexts = {}, + servicesManager, }) => { const isVTK = () => activeContexts.includes(contexts.VTK); const isCornerstone = () => activeContexts.includes(contexts.CORNERSTONE); @@ -59,6 +61,9 @@ const SegmentationPanel = ({ * store with context to make these kind of things less blurry. */ const { configuration } = cornerstoneTools.getModule('segmentation'); + if (configuration.segsTolerance === undefined) { + configuration.segsTolerance = 1e-2; + } const DEFAULT_BRUSH_RADIUS = configuration.radius || 10; /* @@ -87,6 +92,25 @@ const SegmentationPanel = ({ return studyMetadata.getFirstImageId(displaySetInstanceUID); }; + const getAllSegDisplaySets = () => { + const { StudyInstanceUID } = getActiveViewport(); + const studyMetadata = studyMetadataManager.get(StudyInstanceUID); + return studyMetadata.getDerivedDatasets({ + Modality: 'SEG', + }); + }; + + const updateSegDisplaySetsTolerance = tolerance => { + const segDisplaySets = getAllSegDisplaySets(); + segDisplaySets.forEach(segDisplaySet => { + // update tol value + segDisplaySet.tolerance = tolerance; + // reset load flags for allowing retry for seg parsing. + segDisplaySet.isLoaded = false; + segDisplaySet.loadError = false; + }); + }; + const getActiveLabelMaps3D = () => { const { labelmaps3D, activeLabelmapIndex } = getBrushStackState(); return labelmaps3D[activeLabelmapIndex]; @@ -598,7 +622,9 @@ const SegmentationPanel = ({ configuration.outlineWidth = newConfiguration.outlineWidth; configuration.fillAlphaInactive = newConfiguration.fillAlphaInactive; configuration.outlineAlphaInactive = newConfiguration.outlineAlphaInactive; + configuration.segsTolerance = newConfiguration.segsTolerance; onConfigurationChange(newConfiguration); + updateSegDisplaySetsTolerance(configuration.segsTolerance); refreshViewports(); }; @@ -647,6 +673,7 @@ const SegmentationPanel = ({ configuration={configuration} onBack={() => setState(state => ({ ...state, showSettings: false }))} onChange={updateConfiguration} + servicesManager={servicesManager} /> ); } else { diff --git a/extensions/dicom-segmentation/src/components/SegmentationSettings/SegmentationSettings.js b/extensions/dicom-segmentation/src/components/SegmentationSettings/SegmentationSettings.js index 3d637b80f..6da70951b 100644 --- a/extensions/dicom-segmentation/src/components/SegmentationSettings/SegmentationSettings.js +++ b/extensions/dicom-segmentation/src/components/SegmentationSettings/SegmentationSettings.js @@ -4,7 +4,7 @@ import { Range } from '@ohif/ui'; import './SegmentationSettings.css'; -const SegmentationSettings = ({ configuration, onBack, onChange, disabledFields = [] }) => { +const SegmentationSettings = ({ configuration, onBack, onChange, servicesManager, disabledFields = [] }) => { const [state, setState] = useState({ renderFill: configuration.renderFill, renderOutline: configuration.renderOutline, @@ -13,7 +13,8 @@ const SegmentationSettings = ({ configuration, onBack, onChange, disabledFields outlineAlpha: configuration.outlineAlpha, outlineWidth: configuration.outlineWidth, fillAlphaInactive: configuration.fillAlphaInactive, - outlineAlphaInactive: configuration.outlineAlphaInactive + outlineAlphaInactive: configuration.outlineAlphaInactive, + segsTolerance: configuration.segsTolerance, }); useEffect(() => { @@ -133,6 +134,40 @@ const SegmentationSettings = ({ configuration, onBack, onChange, disabledFields )} )} +
+ +
); }; @@ -169,11 +204,12 @@ SegmentationSettings.propTypes = { renderFill: PropTypes.bool.isRequired, renderOutline: PropTypes.bool.isRequired, shouldRenderInactiveLabelmaps: PropTypes.bool.isRequired, - fillAlpha: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, /* TODO: why fillAlpha is string? */ - outlineAlpha: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, /* TODO: why fillAlpha is string? */ + fillAlpha: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + outlineAlpha: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, outlineWidth: PropTypes.number.isRequired, - fillAlphaInactive: PropTypes.number.isRequired, - outlineAlphaInactive: PropTypes.number.isRequired, + fillAlphaInactive: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + outlineAlphaInactive: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + segsTolerance: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, }).isRequired, onBack: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired, diff --git a/extensions/dicom-segmentation/src/getOHIFDicomSegSopClassHandler.js b/extensions/dicom-segmentation/src/getOHIFDicomSegSopClassHandler.js index 8adcd68d4..9b3998dff 100644 --- a/extensions/dicom-segmentation/src/getOHIFDicomSegSopClassHandler.js +++ b/extensions/dicom-segmentation/src/getOHIFDicomSegSopClassHandler.js @@ -62,6 +62,7 @@ export default function getSopClassHandlerModule({ servicesManager }) { SeriesNumber, SeriesDescription, metadata, + tolerance: 1e-2, }; segDisplaySet.getSourceDisplaySet = function( @@ -93,7 +94,7 @@ export default function getSopClassHandlerModule({ servicesManager }) { referencedDisplaySet.SeriesInstanceUID ); - const results = await _parseSeg(segArrayBuffer, imageIds); + const results = await _parseSeg(segArrayBuffer, imageIds, segDisplaySet.tolerance); if (results === undefined) { return; } @@ -149,10 +150,13 @@ export default function getSopClassHandlerModule({ servicesManager }) { }; } -function _parseSeg(arrayBuffer, imageIds) { - const skipOverlapping = false; - const tolerance = 1e-2; - const cornerstoneToolsVersion = 4; +function _parseSeg( + arrayBuffer, + imageIds, + tolerance = 1e-2, + skipOverlapping = false, + cornerstoneToolsVersion = 4 +) { return dcmjs.adapters.Cornerstone.Segmentation.generateToolState( imageIds, arrayBuffer, diff --git a/extensions/dicom-segmentation/src/index.js b/extensions/dicom-segmentation/src/index.js index 17bd246b7..a7d96fa59 100644 --- a/extensions/dicom-segmentation/src/index.js +++ b/extensions/dicom-segmentation/src/index.js @@ -78,6 +78,7 @@ export default { onConfigurationChange={onConfigurationChangeHandler} onSelectedSegmentationChange={onSelectedSegmentationChangeHandler} onDisplaySetLoadFailure={onDisplaySetLoadFailureHandler} + servicesManager={servicesManager} /> ); };