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 1/7] =?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': ''
From 370f99eabcb91ed43354c863301210376988c1f1 Mon Sep 17 00:00:00 2001
From: wangxiaoshuang <825034831@qq.com>
Date: Mon, 22 Jun 2026 16:58:39 +0800
Subject: [PATCH 2/7] =?UTF-8?q?=E5=88=86=E5=89=B2=E7=90=83=E4=BD=93?=
=?UTF-8?q?=E5=B7=A5=E5=85=B7=E8=A7=A6=E5=8F=91=E8=87=AA=E5=8A=A8=E8=AE=A1?=
=?UTF-8?q?=E7=AE=97=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../reading/dicoms3D/components/Segmentations.vue | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
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 1a98ef19..71dc8bea 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue
@@ -1577,7 +1577,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;
}
@@ -1642,12 +1642,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)
From 2e388db02ca1da073162009e0588a8edae263dc6 Mon Sep 17 00:00:00 2001
From: wangxiaoshuang <825034831@qq.com>
Date: Mon, 22 Jun 2026 17:43:22 +0800
Subject: [PATCH 3/7] =?UTF-8?q?=E5=88=86=E5=89=B2=E6=96=B0=E5=B7=A5?=
=?UTF-8?q?=E5=85=B7=E7=A6=81=E7=94=A8=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../trials-panel/reading/dicoms3D/components/ReadPage.vue | 2 ++
.../reading/dicoms3D/components/Segmentations.vue | 6 +++---
2 files changed, 5 insertions(+), 3 deletions(-)
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 205d0398..4c9b2d43 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue
@@ -2990,6 +2990,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 71dc8bea..d2f2d82b 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue
@@ -143,7 +143,7 @@
{{
$t('trials:reading:Segmentations:title:InactiveSegmentationsShow')
- }}
+ }}
@@ -326,7 +326,7 @@
{{
$t('trials:reading:Segmentations:button:recovery')
- }}
+ }}
@@ -1612,7 +1612,7 @@ export default {
label: "Mean Pixel",
name: "sulpeak",
unit: "SUL",
- value: suvFactor.suvlbm ? segmentStat.mean.value * suvFactor.suvbw / suvFactor.suvlbm : 0,
+ value: suvFactor.suvlbm ? segmentStat.mean.value * suvFactor.suvlbm / suvFactor.suvbw : 0,
}
}
let segmentGroup = this.segmentList.find(item => item.segmentationId === segmentationId)
From bddcadeb896e716a3f6d0aa1a31f78a43b4d30ac Mon Sep 17 00:00:00 2001
From: wangxiaoshuang <825034831@qq.com>
Date: Tue, 23 Jun 2026 10:31:10 +0800
Subject: [PATCH 4/7] =?UTF-8?q?sulpeak=E8=AE=A1=E7=AE=97=E5=85=AC=E5=BC=8F?=
=?UTF-8?q?=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../reading/dicoms3D/components/Segmentations.vue | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
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 d2f2d82b..bffa9fb0 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue
@@ -143,7 +143,7 @@
{{
$t('trials:reading:Segmentations:title:InactiveSegmentationsShow')
- }}
+ }}
@@ -326,7 +326,7 @@
{{
$t('trials:reading:Segmentations:button:recovery')
- }}
+ }}
@@ -1612,7 +1612,7 @@ export default {
label: "Mean Pixel",
name: "sulpeak",
unit: "SUL",
- value: suvFactor.suvlbm ? segmentStat.mean.value * suvFactor.suvlbm / suvFactor.suvbw : 0,
+ value: suvFactor.suvlbm && suvFactor.suvbw ? segmentStat.mean.value * suvFactor.suvlbm / suvFactor.suvbw : 0,
}
}
let segmentGroup = this.segmentList.find(item => item.segmentationId === segmentationId)
From ffbf12f845099bc600a28c2e02feea83c74c54d1 Mon Sep 17 00:00:00 2001
From: wangxiaoshuang <825034831@qq.com>
Date: Wed, 24 Jun 2026 15:17:18 +0800
Subject: [PATCH 5/7] =?UTF-8?q?=E5=88=86=E5=89=B2=E7=90=83=E4=BD=93?=
=?UTF-8?q?=E5=B7=A5=E5=85=B7=E5=9B=BE=E6=A0=87=E6=9B=B4=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/icons/svg/sphericalBrush.svg | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/icons/svg/sphericalBrush.svg b/src/icons/svg/sphericalBrush.svg
index 01a40150..565c0f48 100644
--- a/src/icons/svg/sphericalBrush.svg
+++ b/src/icons/svg/sphericalBrush.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
From 30fdd9176462204d7341945bfac75adc05eb0b85 Mon Sep 17 00:00:00 2001
From: wangxiaoshuang <825034831@qq.com>
Date: Mon, 29 Jun 2026 11:41:17 +0800
Subject: [PATCH 6/7] =?UTF-8?q?=E9=9D=9EDICOM=E9=98=85=E7=89=87=E9=A1=B5?=
=?UTF-8?q?=E9=9D=A2=E6=A0=B7=E5=BC=8F=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../visit-review/components/FileViewer.vue | 57 ++++++++-----------
1 file changed, 23 insertions(+), 34 deletions(-)
diff --git a/src/views/trials/trials-panel/reading/visit-review/components/FileViewer.vue b/src/views/trials/trials-panel/reading/visit-review/components/FileViewer.vue
index 1c327352..c996f5ef 100644
--- a/src/views/trials/trials-panel/reading/visit-review/components/FileViewer.vue
+++ b/src/views/trials/trials-panel/reading/visit-review/components/FileViewer.vue
@@ -32,13 +32,8 @@
-
+