增加对于SULpeak测量的支持
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
8b766672b5
commit
abbc15cb09
|
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1782109630167" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6972" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 512m-400 0a400 400 0 1 0 800 0 400 400 0 1 0-800 0Z" p-id="6973" fill="#e6e6e6"></path></svg>
|
||||||
|
After Width: | Height: | Size: 431 B |
|
|
@ -19,7 +19,7 @@
|
||||||
<div :title="$t('trials:Segmentations:tools:thresholecircle')"
|
<div :title="$t('trials:Segmentations:tools:thresholecircle')"
|
||||||
:class="['tool-item', ThresholdTools.includes(activeTool) && segmentList.length > 0 ? 'tool-item-active' : '']"
|
:class="['tool-item', ThresholdTools.includes(activeTool) && segmentList.length > 0 ? 'tool-item-active' : '']"
|
||||||
:style="{ cursor: isMPR || segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
:style="{ cursor: isMPR || segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
||||||
@click.prevent="initThreshold">
|
@click.prevent="initThreshold()">
|
||||||
<svg-icon icon-class="thresholecircle" class="svg-icon" />
|
<svg-icon icon-class="thresholecircle" class="svg-icon" />
|
||||||
</div>
|
</div>
|
||||||
<div :title="$t('trials:Segmentations:tools:circularbrush')"
|
<div :title="$t('trials:Segmentations:tools:circularbrush')"
|
||||||
|
|
@ -28,6 +28,12 @@
|
||||||
@click.prevent="setToolActive('CircularBrush')">
|
@click.prevent="setToolActive('CircularBrush')">
|
||||||
<svg-icon icon-class="circularbrush" class="svg-icon" />
|
<svg-icon icon-class="circularbrush" class="svg-icon" />
|
||||||
</div>
|
</div>
|
||||||
|
<div :title="$t('trials:Segmentations:tools:SphericalBrush')"
|
||||||
|
:class="['tool-item', activeTool === 'SphericalBrush' && segmentList.length > 0 ? 'tool-item-active' : '']"
|
||||||
|
:style="{ cursor: isMPR || segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
||||||
|
@click.prevent="initThreshold('SphericalBrush')">
|
||||||
|
<svg-icon icon-class="sphericalBrush" class="svg-icon" />
|
||||||
|
</div>
|
||||||
<div :class="['tool-item', activeTool === 'CircularEraser' && segmentList.length > 0 ? 'tool-item-active' : '']"
|
<div :class="['tool-item', activeTool === 'CircularEraser' && segmentList.length > 0 ? 'tool-item-active' : '']"
|
||||||
:style="{ cursor: isMPR || segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
:style="{ cursor: isMPR || segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
||||||
:title="$t('trials:Segmentations:tools:Eraser')"
|
:title="$t('trials:Segmentations:tools:Eraser')"
|
||||||
|
|
@ -40,7 +46,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="ConfigBox">
|
<div class="ConfigBox">
|
||||||
<div class="EraserConfig"
|
<div class="EraserConfig"
|
||||||
v-if="activeTool === 'CircularEraser' || activeTool === 'CircularBrush' || ThresholdTools.includes(activeTool)">
|
v-if="activeTool === 'SphericalBrush' || activeTool === 'CircularEraser' || activeTool === 'CircularBrush' || ThresholdTools.includes(activeTool)">
|
||||||
<span>{{ $t('trials:reading:Segmentations:title:EraserConfigSection') }}</span>
|
<span>{{ $t('trials:reading:Segmentations:title:EraserConfigSection') }}</span>
|
||||||
<el-select v-model="sliderMax" placeholder="" size="small" @change="handleSliderChange">
|
<el-select v-model="sliderMax" placeholder="" size="small" @change="handleSliderChange">
|
||||||
<el-option v-for="item in sliderSection" :key="item.id" :label="item.label"
|
<el-option v-for="item in sliderSection" :key="item.id" :label="item.label"
|
||||||
|
|
@ -48,8 +54,8 @@
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="EraserConfig"
|
<div class="EraserConfig RadiusConfig"
|
||||||
v-if="activeTool === 'CircularEraser' || activeTool === 'CircularBrush' || ThresholdTools.includes(activeTool)">
|
v-if="activeTool === 'SphericalBrush' || activeTool === 'CircularEraser' || activeTool === 'CircularBrush' || ThresholdTools.includes(activeTool)">
|
||||||
<span>{{ $t('trials:reading:Segmentations:title:EraserConfig') }}</span>
|
<span>{{ $t('trials:reading:Segmentations:title:EraserConfig') }}</span>
|
||||||
<el-slider v-model="brushSize" show-input :step="sliderStep" :max="sliderMax" input-size="mini"
|
<el-slider v-model="brushSize" show-input :step="sliderStep" :max="sliderMax" input-size="mini"
|
||||||
:show-input-controls="false" />
|
:show-input-controls="false" />
|
||||||
|
|
@ -137,7 +143,7 @@
|
||||||
</el-switch>
|
</el-switch>
|
||||||
<span style="margin-left: 5px;">{{
|
<span style="margin-left: 5px;">{{
|
||||||
$t('trials:reading:Segmentations:title:InactiveSegmentationsShow')
|
$t('trials:reading:Segmentations:title:InactiveSegmentationsShow')
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="segmentList.length > 0">
|
<template v-if="segmentList.length > 0">
|
||||||
|
|
@ -320,7 +326,7 @@
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button type="text" @click.stop="restoreSegmentationVersion(scope.row)">{{
|
<el-button type="text" @click.stop="restoreSegmentationVersion(scope.row)">{{
|
||||||
$t('trials:reading:Segmentations:button:recovery')
|
$t('trials:reading:Segmentations:button:recovery')
|
||||||
}}</el-button>
|
}}</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
@ -636,8 +642,13 @@ export default {
|
||||||
handleClickPopover(item) {
|
handleClickPopover(item) {
|
||||||
this.popoverId = `popover-${item.segmentationId}_${item.segmentIndex}`
|
this.popoverId = `popover-${item.segmentationId}_${item.segmentIndex}`
|
||||||
},
|
},
|
||||||
initThreshold() {
|
initThreshold(key = null) {
|
||||||
if (this.isMPR) return false
|
if (this.isMPR) return false
|
||||||
|
if (key === 'SphericalBrush') {
|
||||||
|
this.setToolActive(this.ThresholdTools[1], 'SphericalBrush')
|
||||||
|
this.setSphericalBrushConfig()
|
||||||
|
return false
|
||||||
|
}
|
||||||
if (!this.ThresholdTools.includes(this.activeTool)) {
|
if (!this.ThresholdTools.includes(this.activeTool)) {
|
||||||
this.setToolActive(this.ThresholdTools[0])
|
this.setToolActive(this.ThresholdTools[0])
|
||||||
this.thresholdType = 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.segmentList.length <= 0) return false
|
||||||
if (this.curSegment.lock) return false
|
if (this.curSegment.lock) return false
|
||||||
if (this.isMPR) return false
|
if (this.isMPR) return false
|
||||||
|
|
@ -786,10 +797,15 @@ export default {
|
||||||
// if (toolName === 'CircularEraser') {
|
// if (toolName === 'CircularEraser') {
|
||||||
// console.log(toolGroup.getToolInstance(toolName))
|
// console.log(toolGroup.getToolInstance(toolName))
|
||||||
// }
|
// }
|
||||||
this.$emit('update:activeTool', toolName)
|
if (name) {
|
||||||
this.setBrushSize(toolName)
|
this.$emit('update:activeTool', name)
|
||||||
if (this.ThresholdTools.includes(toolName)) {
|
this.setBrushSize(name)
|
||||||
this.setBrushThreshold()
|
} 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') {
|
if (toolName === 'ThresholdSphere') {
|
||||||
this.setDynamicRadius()
|
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() {
|
setDynamicRadius() {
|
||||||
let volume = cache.getVolume(this.series.SeriesInstanceUid);
|
let volume = cache.getVolume(this.series.SeriesInstanceUid);
|
||||||
|
|
@ -1502,7 +1533,7 @@ export default {
|
||||||
let constant = numFrames * spacing[2] / 100
|
let constant = numFrames * spacing[2] / 100
|
||||||
this.brushThreshold.dynamicRadius = Math.ceil(this.brushSize * constant)
|
this.brushThreshold.dynamicRadius = Math.ceil(this.brushSize * constant)
|
||||||
},
|
},
|
||||||
setBrushThreshold() {
|
setBrushThreshold(OBJ = null) {
|
||||||
const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}`
|
const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}`
|
||||||
let brushThreshold = {
|
let brushThreshold = {
|
||||||
isDynamic: this.brushThreshold.isDynamic,
|
isDynamic: this.brushThreshold.isDynamic,
|
||||||
|
|
@ -1511,6 +1542,7 @@ export default {
|
||||||
if (!this.brushThreshold.isDynamic) {
|
if (!this.brushThreshold.isDynamic) {
|
||||||
brushThreshold.range = this.brushThreshold.range
|
brushThreshold.range = this.brushThreshold.range
|
||||||
}
|
}
|
||||||
|
if (OBJ) brushThreshold = OBJ
|
||||||
CStUtils.segmentation.setBrushThresholdForToolGroup(toolGroupId, brushThreshold);
|
CStUtils.segmentation.setBrushThresholdForToolGroup(toolGroupId, brushThreshold);
|
||||||
},
|
},
|
||||||
async createSegmentation(segmentationId) {
|
async createSegmentation(segmentationId) {
|
||||||
|
|
@ -1563,12 +1595,26 @@ export default {
|
||||||
console.log(stats)
|
console.log(stats)
|
||||||
if (mode === 'individual') {
|
if (mode === 'individual') {
|
||||||
const segmentStats = stats;
|
const segmentStats = stats;
|
||||||
|
|
||||||
for (const segmentIndex of indices) {
|
for (const segmentIndex of indices) {
|
||||||
if (segmentStats[segmentIndex]) {
|
if (segmentStats[segmentIndex]) {
|
||||||
const segmentStat = segmentStats[segmentIndex];
|
const segmentStat = segmentStats[segmentIndex];
|
||||||
// console.log(segmentStat, 'segmentStat')
|
// console.log(segmentStat, 'segmentStat')
|
||||||
segmentStat.count.label = 'Voxels';
|
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)
|
let segmentGroup = this.segmentList.find(item => item.segmentationId === segmentationId)
|
||||||
if (segmentGroup) {
|
if (segmentGroup) {
|
||||||
let segment = segmentGroup.segments.find(item => item.segmentIndex === segmentIndex)
|
let segment = segmentGroup.segments.find(item => item.segmentIndex === segmentIndex)
|
||||||
|
|
@ -2477,6 +2523,21 @@ export default {
|
||||||
.EraserConfig {
|
.EraserConfig {
|
||||||
margin: 5px 0;
|
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 {
|
::v-deep .el-input-number {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -409,7 +409,7 @@ const config = {
|
||||||
'name': 'Labelmap分割',
|
'name': 'Labelmap分割',
|
||||||
'icon': 'labelmap',
|
'icon': 'labelmap',
|
||||||
'toolName': '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',
|
'i18nKey': 'trials:reading:button:Labelmap',
|
||||||
'isDisabled': false,
|
'isDisabled': false,
|
||||||
'disabledReason': ''
|
'disabledReason': ''
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue