From abbc15cb0973573134e22ba6872cb5669740a376 Mon Sep 17 00:00:00 2001
From: wangxiaoshuang <825034831@qq.com>
Date: Mon, 22 Jun 2026 15:08:51 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=B9=E4=BA=8ESULpeak?=
=?UTF-8?q?=E6=B5=8B=E9=87=8F=E7=9A=84=E6=94=AF=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/icons/svg/sphericalBrush.svg | 1 +
.../dicoms3D/components/Segmentations.vue | 89 ++++++++++++++++---
.../reading/dicoms3D/components/toolConfig.js | 2 +-
3 files changed, 77 insertions(+), 15 deletions(-)
create mode 100644 src/icons/svg/sphericalBrush.svg
diff --git a/src/icons/svg/sphericalBrush.svg b/src/icons/svg/sphericalBrush.svg
new file mode 100644
index 00000000..01a40150
--- /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/Segmentations.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue
index 36935e99..1a98ef19 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') }}
@@ -137,7 +143,7 @@
{{
$t('trials:reading:Segmentations:title:InactiveSegmentationsShow')
- }}
+ }}
@@ -320,7 +326,7 @@
{{
$t('trials:reading:Segmentations:button:recovery')
- }}
+ }}
@@ -636,8 +642,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]
@@ -757,7 +768,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
@@ -786,10 +797,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()
+ }
}
}
@@ -1495,6 +1511,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);
@@ -1502,7 +1533,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,
@@ -1511,6 +1542,7 @@ export default {
if (!this.brushThreshold.isDynamic) {
brushThreshold.range = this.brushThreshold.range
}
+ if (OBJ) brushThreshold = OBJ
CStUtils.segmentation.setBrushThresholdForToolGroup(toolGroupId, brushThreshold);
},
async createSegmentation(segmentationId) {
@@ -1563,12 +1595,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 ? segmentStat.mean.value * suvFactor.suvbw / suvFactor.suvlbm : 0,
+ }
+ }
let segmentGroup = this.segmentList.find(item => item.segmentationId === segmentationId)
if (segmentGroup) {
let segment = segmentGroup.segments.find(item => item.segmentIndex === segmentIndex)
@@ -2477,6 +2523,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': ''