Re IDC #3077: Seg series thumbnail selection (#3078)

* fix: #3077 update seg tolerance popup and update seg thumbnail warning

* jump to first segment item image

* Shows warning message only once on onChange
This commit is contained in:
Gitanjali 2023-01-17 09:50:25 -08:00 committed by GitHub
parent cb9aa6a765
commit 24bbf2b190
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 157 additions and 25 deletions

View File

@ -0,0 +1,100 @@
import csTools from 'cornerstone-tools';
import cs from 'cornerstone-core';
import OHIF from '@ohif/core';
import DICOMSegTempCrosshairsTool from './tools/DICOMSegTempCrosshairsTool';
import refreshViewports from './utils/refreshViewports';
const { studyMetadataManager } = OHIF.utils;
const commandsModule = ({ commandsManager }) => {
const actions = {
jumpToFirstSegment: ({ viewports }) => {
try {
const { activeViewportIndex, viewportSpecificData } = viewports;
const viewport = viewportSpecificData[activeViewportIndex];
const { StudyInstanceUID, displaySetInstanceUID } = viewport;
const studyMetadata = studyMetadataManager.get(StudyInstanceUID);
const firstImageId = studyMetadata.getFirstImageId(
displaySetInstanceUID
);
const module = csTools.getModule('segmentation');
const brushStackState = module.state.series[firstImageId];
const { labelmaps3D, activeLabelmapIndex } = brushStackState;
const { labelmaps2D } = labelmaps3D[activeLabelmapIndex];
const firstLabelMap2D = labelmaps2D.find(value => !!value);
const firstSegment = firstLabelMap2D.segmentsOnLabelmap[0];
const segmentNumber = firstSegment;
const validIndexList = [];
labelmaps2D.forEach((labelMap2D, index) => {
if (labelMap2D.segmentsOnLabelmap.includes(segmentNumber)) {
validIndexList.push(index);
}
});
const avg = array => array.reduce((a, b) => a + b) / array.length;
const average = avg(validIndexList);
const closest = validIndexList.reduce((prev, curr) => {
return Math.abs(curr - average) < Math.abs(prev - average)
? curr
: prev;
});
const enabledElements = cs.getEnabledElements();
const element = enabledElements[activeViewportIndex].element;
const toolState = csTools.getToolState(element, 'stack');
if (!toolState) return;
const imageIds = toolState.data[0].imageIds;
const imageId = imageIds[closest];
const frameIndex = imageIds.indexOf(imageId);
const SOPInstanceUID = cs.metaData.get('SOPInstanceUID', imageId);
cs.getEnabledElements().forEach(enabledElement => {
cs.updateImage(enabledElement.element);
});
DICOMSegTempCrosshairsTool.addCrosshair(
element,
imageId,
segmentNumber
);
cs.getEnabledElements().forEach(enabledElement => {
cs.updateImage(enabledElement.element);
});
const refreshViewports = false;
commandsManager.runCommand('jumpToImage', {
StudyInstanceUID,
SOPInstanceUID,
frameIndex,
activeViewportIndex,
refreshViewports,
});
} catch (error) {
console.log('Error in moving to the first segment slice');
}
},
};
const definitions = {
jumpToFirstSegment: {
commandFn: actions.jumpToFirstSegment,
storeContexts: ['viewports'],
options: {},
},
};
return {
definitions,
defaultContext: 'VIEWER',
};
};
export default commandsModule;

View File

@ -29,6 +29,32 @@ const SegmentationSettings = ({ configuration, onBack, onChange, servicesManager
setState(state => ({ ...state, [field]: value })); setState(state => ({ ...state, [field]: value }));
}; };
const once = fn => (...args) => {
if (!fn) return;
fn(...args);
fn = null;
};
const segTolValue = document.getElementById('segToleranceValue');
if (segTolValue) {
segTolValue.onchange = once(function() {
const { UINotificationService, LoggerService } = servicesManager.services;
const error = new Error(
'Segmentation loader tolerance changed.\
This operation can potentially generate errors in the Segmentation parsing.'
);
LoggerService.error({ error, message: error.message });
UINotificationService.show({
title: 'Segmentation panel',
message: error.message,
type: 'warning',
autoClose: true,
});
});
}
const toFloat = value => parseFloat(value / 100).toFixed(2); const toFloat = value => parseFloat(value / 100).toFixed(2);
return ( return (
@ -138,32 +164,23 @@ const SegmentationSettings = ({ configuration, onBack, onChange, servicesManager
<label style={{ margin: '0 15px' }}> <label style={{ margin: '0 15px' }}>
Tolerance: Tolerance:
<input <input
id="segToleranceValue"
style={{ margin: '0 15px' }} style={{ margin: '0 15px' }}
label="Tolerance" label="Tolerance"
onKeyPress={event => { onKeyPress={event => {
const validate = string => { const validate = string => {
let rgx = /[^-.e0-9]+/g; let rgx = /[^-.e0-9]+/g;
return string.match(rgx); return string.match(rgx);
}; };
if (validate(event.key)) { if (validate(event.key)) {
event.preventDefault(); event.preventDefault();
} }
}}
onChange={event => {
save('segsTolerance', event.target.value);
const { UINotificationService, LoggerService } = servicesManager.services;
const error = new Error('Segmentation loader tolerance changed. This operation can potentially generate errors in the Segmentation parsing.');
LoggerService.error({ error, message: error.message });
UINotificationService.show({
title: 'Segmentation panel',
message: error.message,
type: 'warning',
autoClose: true,
});
} }
} }
onChange={event => {
save('segsTolerance', event.target.value);
}}
value={state.segsTolerance} value={state.segsTolerance}
/> />
</label> </label>

View File

@ -6,6 +6,7 @@ import toolbarModule from './toolbarModule.js';
import getSopClassHandlerModule from './getOHIFDicomSegSopClassHandler.js'; import getSopClassHandlerModule from './getOHIFDicomSegSopClassHandler.js';
import SegmentationPanel from './components/SegmentationPanel/SegmentationPanel.js'; import SegmentationPanel from './components/SegmentationPanel/SegmentationPanel.js';
import { version } from '../package.json'; import { version } from '../package.json';
import commandsModule from './commandsModule.js';
const { studyMetadataManager } = OHIF.utils; const { studyMetadataManager } = OHIF.utils;
export default { export default {
@ -121,6 +122,15 @@ export default {
}); });
}; };
const onSegmentationsCompletelyLoaded = () => {
commandsManager.runCommand('jumpToFirstSegment');
};
document.addEventListener(
'segseriesselected',
onSegmentationsCompletelyLoaded
);
document.addEventListener( document.addEventListener(
'extensiondicomsegmentationsegloaded', 'extensiondicomsegmentationsegloaded',
onSegmentationsLoaded onSegmentationsLoaded
@ -182,5 +192,8 @@ export default {
defaultContext: ['VIEWER'], defaultContext: ['VIEWER'],
}; };
}, },
getCommandsModule({ commandsManager, servicesManager }) {
return commandsModule({ commandsManager, servicesManager });
},
getSopClassHandlerModule, getSopClassHandlerModule,
}; };

View File

@ -54,7 +54,9 @@ const mapDispatchToProps = (dispatch, ownProps) => {
detail: { activatedLabelmapIndex: activatedLabelmapIndex }, detail: { activatedLabelmapIndex: activatedLabelmapIndex },
} }
); );
const segThumbnailSelected = new CustomEvent('segseriesselected');
document.dispatchEvent(selectionFired); document.dispatchEvent(selectionFired);
document.dispatchEvent(segThumbnailSelected);
}); });
} else if (Modality !== 'SR') { } else if (Modality !== 'SR') {
displaySet = displaySet.getSourceDisplaySet(ownProps.studyMetadata); displaySet = displaySet.getSourceDisplaySet(ownProps.studyMetadata);

View File

@ -505,14 +505,14 @@ const _checkForDerivedDisplaySets = async function(displaySet, study) {
* @returns {[string]} an array of strings containing the warnings * @returns {[string]} an array of strings containing the warnings
*/ */
const _checkForSeriesInconsistencesWarnings = async function(displaySet) { const _checkForSeriesInconsistencesWarnings = async function(displaySet) {
if (displaySet.inconsistencyWarnings) {
// warnings already checked and cached in displaySet
return displaySet.inconsistencyWarnings;
}
const inconsistencyWarnings = []; const inconsistencyWarnings = [];
if (displaySet.Modality !== 'SEG') { if (displaySet.Modality !== 'SEG') {
// warnings already checked and cached in displaySet
if (displaySet.inconsistencyWarnings) {
return displaySet.inconsistencyWarnings;
}
if ( if (
displaySet.reconstructionIssues && displaySet.reconstructionIssues &&
displaySet.reconstructionIssues.length !== 0 displaySet.reconstructionIssues.length !== 0