diff --git a/src/icons/svg/sphericalBrush.svg b/src/icons/svg/sphericalBrush.svg new file mode 100644 index 00000000..565c0f48 --- /dev/null +++ b/src/icons/svg/sphericalBrush.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue index 15af978e..9261590f 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue @@ -3076,6 +3076,8 @@ export default { } } else if (this.activeTool === FusionJumpToPointTool.toolName) { this.setFusionMipJumpEnabled(false) + } else if (this.activeTool === 'SphericalBrush') { + toolGroup.setToolDisabled('ThresholdSphere') } else { toolGroup.setToolPassive(this.activeTool) } diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue index b55d7595..613efaf4 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue @@ -19,7 +19,7 @@
+ @click.prevent="initThreshold()">
+
+ +
+ v-if="activeTool === 'SphericalBrush' || activeTool === 'CircularEraser' || activeTool === 'CircularBrush' || ThresholdTools.includes(activeTool)"> {{ $t('trials:reading:Segmentations:title:EraserConfigSection') }}
-
+
{{ $t('trials:reading:Segmentations:title:EraserConfig') }} @@ -656,8 +662,13 @@ export default { handleClickPopover(item) { this.popoverId = `popover-${item.segmentationId}_${item.segmentIndex}` }, - initThreshold() { + initThreshold(key = null) { if (this.isMPR) return false + if (key === 'SphericalBrush') { + this.setToolActive(this.ThresholdTools[1], 'SphericalBrush') + this.setSphericalBrushConfig() + return false + } if (!this.ThresholdTools.includes(this.activeTool)) { this.setToolActive(this.ThresholdTools[0]) this.thresholdType = this.ThresholdTools[0] @@ -777,7 +788,7 @@ export default { } }, - setToolActive(toolName) { + setToolActive(toolName, name = null) { if (this.segmentList.length <= 0) return false if (this.curSegment.lock) return false if (this.isMPR) return false @@ -806,10 +817,15 @@ export default { // if (toolName === 'CircularEraser') { // console.log(toolGroup.getToolInstance(toolName)) // } - this.$emit('update:activeTool', toolName) - this.setBrushSize(toolName) - if (this.ThresholdTools.includes(toolName)) { - this.setBrushThreshold() + if (name) { + this.$emit('update:activeTool', name) + this.setBrushSize(name) + } else { + this.$emit('update:activeTool', toolName) + this.setBrushSize(toolName) + if (this.ThresholdTools.includes(toolName)) { + this.setBrushThreshold() + } } } @@ -1516,6 +1532,21 @@ export default { if (toolName === 'ThresholdSphere') { this.setDynamicRadius() } + if (toolName === 'SphericalBrush') { + this.setSphericalBrushConfig() + } + }, + setSphericalBrushConfig() { + let volume = cache.getVolume(this.series.SeriesInstanceUid); + let { spacing, numFrames } = volume + let constant = numFrames * spacing[2] / 100 + let dynamicRadius = Math.ceil(this.brushSize * constant) + let obj = { + dynamicRadius: dynamicRadius, + isDynamic: false, + range: [-10000, 100000] + } + this.setBrushThreshold(obj) }, setDynamicRadius() { let volume = cache.getVolume(this.series.SeriesInstanceUid); @@ -1523,7 +1554,7 @@ export default { let constant = numFrames * spacing[2] / 100 this.brushThreshold.dynamicRadius = Math.ceil(this.brushSize * constant) }, - setBrushThreshold() { + setBrushThreshold(OBJ = null) { const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}` let brushThreshold = { isDynamic: this.brushThreshold.isDynamic, @@ -1532,6 +1563,7 @@ export default { if (!this.brushThreshold.isDynamic) { brushThreshold.range = this.brushThreshold.range } + if (OBJ) brushThreshold = OBJ CStUtils.segmentation.setBrushThresholdForToolGroup(toolGroupId, brushThreshold); }, async createSegmentation(segmentationId) { @@ -1566,7 +1598,7 @@ export default { }, segmentationModifiedCallback(evt) { const { detail } = evt; - let tools = [...this.ThresholdTools, ...this.tools] + let tools = [...this.ThresholdTools, ...this.tools, 'SphericalBrush'] if (!detail || detail.segmentIndex === 255 || !this.activeTool || !tools.includes(this.activeTool)) { return; } @@ -1584,12 +1616,26 @@ export default { console.log(stats) if (mode === 'individual') { const segmentStats = stats; - for (const segmentIndex of indices) { if (segmentStats[segmentIndex]) { const segmentStat = segmentStats[segmentIndex]; // console.log(segmentStat, 'segmentStat') segmentStat.count.label = 'Voxels'; + if (this.series.Modality === 'PT') { + const renderingEngine = getRenderingEngine(this.renderingEngineId) + const viewportId = `${this.viewportKey}-${this.activeViewportIndex}` + const viewport = renderingEngine.getViewport(viewportId); + let imageIds = viewport.getImageIds(this.series.SeriesInstanceUid) + let imageId = imageIds[0] + const suvFactor = metaData.get('scalingModule', imageId) || {}; + console.log(suvFactor, 'suvFactor') + segmentStat.sulpeak = { + label: "Mean Pixel", + name: "sulpeak", + unit: "SUL", + value: suvFactor.suvlbm && suvFactor.suvbw ? segmentStat.mean.value * suvFactor.suvlbm / suvFactor.suvbw : 0, + } + } let segmentGroup = this.segmentList.find(item => item.segmentationId === segmentationId) if (segmentGroup) { let segment = segmentGroup.segments.find(item => item.segmentIndex === segmentIndex) @@ -1617,12 +1663,12 @@ export default { contentMouseup() { try { // console.log("segment contentMouseup") - if (!this.drawing) return false if (this.timeoutId) { clearTimeout(this.timeoutId); this.timeoutId = null; } this.timeoutId = setTimeout(() => { + if (!this.drawing) return false this.timeoutId = null; this.drawing = false; let segmentGroup = this.segmentList.find(item => item.segmentationId === this.segmentationId) @@ -2498,6 +2544,21 @@ export default { .EraserConfig { margin: 5px 0; + ::v-deep .el-input-number { + width: 90px; + } + + ::v-deep .el-input-number.is-without-controls .el-input__inner { + padding: 0 10px; + width: 90px; + } + + ::v-deep .el-radio-button__inner { + width: 105px; + } +} + +.RadiusConfig { ::v-deep .el-input-number { width: 50px; } diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/toolConfig.js b/src/views/trials/trials-panel/reading/dicoms3D/components/toolConfig.js index 17274ebe..ec331e93 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/toolConfig.js +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/toolConfig.js @@ -409,7 +409,7 @@ const config = { 'name': 'Labelmap分割', 'icon': 'labelmap', 'toolName': 'Labelmap', - 'props': ['max', 'min', 'volume', 'count', 'mean', 'stdDev', 'length', 'width'], + 'props': ['max', 'min', 'volume', 'count', 'mean', 'stdDev', 'length', 'width', 'sulpeak'], 'i18nKey': 'trials:reading:button:Labelmap', 'isDisabled': false, 'disabledReason': ''