AnalysisSystemForRadionucli.../src/views/spectrumAnalysis/beta-analysis.vue

776 lines
21 KiB
Vue

<template>
<div class="beta-gamma-analysis">
<a-spin :spinning="isLoading">
<!-- 二级交互栏 -->
<div class="spectrum-analysis-sub-operators">
<pop-over-with-icon placement="bottomLeft">
Detailed-Information
<beta-gamma-detailed-infomation slot="content" :data="spectrumData" />
</pop-over-with-icon>
<custom-select
v-model="spectraType"
:options="SampleType"
@change="changeChartByType"
style="width: 246px"
class="sample-select"
></custom-select>
<div class="spectrum-analysis-sub-operators-roi" v-for="(_, index) in 4" :key="index">
<div class="spectrum-analysis-sub-operators-roi-name" :style="{ color: ROIColors[index] }">
ROI{{ index + 1 }}
</div>
<a-input-group>
<a-input
type="number"
v-model="roiParamList[index][0]"
class="spectrum-analysis-sub-operators-roi-input"
placeholder="Beta1"
:disabled="spectraType !== 'sample'"
/>
<span class="spectrum-analysis-sub-operators-roi-split">,</span>
<a-input
type="number"
v-model="roiParamList[index][1]"
class="spectrum-analysis-sub-operators-roi-input"
placeholder="Beta2"
:disabled="spectraType !== 'sample'"
/>
</a-input-group>
</div>
<a-button
type="primary"
class="spectrum-analysis-sub-operators-button"
:disabled="spectraType !== 'sample'"
@click="handleUpdate"
>
Update
</a-button>
</div>
<!-- 二级交互栏结束 -->
<!-- 主体部分 -->
<div class="beta-gamma-analysis-main">
<!-- 左侧图表部分 -->
<div class="beta-gamma-analysis-main-left">
<beta-gamma-chart-container>
<template slot="title"> Beta-Gamma Spectrum: {{ currSpectrum }} </template>
<beta-gamma-spectrum
ref="betaChartRef"
:betaEnergyData="betaEnergyData"
:gammaEnergyData="gammaEnergyData"
:isLoading.sync="isLoading"
:disabled="spectraType !== 'sample'"
@boundaryChange="handleBoundaryChange"
@open-modal="handleOpenModal"
/>
</beta-gamma-chart-container>
</div>
<!-- 左侧图表结束 -->
<!-- 右侧开始 -->
<div class="beta-gamma-analysis-main-right">
<beta-gamma-chart-container>
<template slot="title"> Beta-Gated-Gamma-Spectrum </template>
<roi-limits
ref="RoiChartRef"
:ROILists="ROILists"
:ROIAnalyzeLists="ROIAnalyzeLists"
:gammaEnergyData="gammaEnergyData"
/>
</beta-gamma-chart-container>
<!-- 底部显示 -->
<div class="beta-gamma-analysis-main-bottom">
<div class="beta-gamma-analysis-main-bottom-left">
<beta-gamma-chart-container>
<template slot="title"> Result display </template>
<result-display-beta :data="resultDisplay" @sendFlag="handleGetFlag"></result-display-beta>
</beta-gamma-chart-container>
</div>
</div>
<!-- 底部显示结束 -->
</div>
<!-- 右侧结束 -->
</div>
<!-- 主体部分结束 -->
</a-spin>
<!-- Gamma 按钮的弹窗 -->
<gamma-modal ref="gammaModalRef" />
<!-- Gamma 按钮的弹窗结束 -->
<!-- Beta 按钮的弹窗 -->
<beta-modal ref="betaModalRef" />
<!-- Beta 按钮的弹窗结束 -->
<!-- Arr和RRR弹窗 -->
<self-station-arr-rrr-modal ref="ARR_RRRModalRef" />
<!-- Arr和RRR弹窗结束 -->
<!-- Spectrum弹窗 -->
<self-station-spectrum-modal ref="spectrumModalRef" />
<!-- Spectrum弹窗结束 -->
<!-- Peak Infomation弹窗 -->
<self-station-peak-infomation ref="peakInfoModalRef" />
<!-- Peak Infomation弹窗结束 -->
<!-- 自动分析日志弹窗 -->
<self-station-automatic-analysis-log-modal ref="autoAnalysisLogRef" />
<!-- 自动分析日志弹窗结束 -->
<!-- BgLog -->
<self-station-bg-log-viewer ref="bgLogViewerRef" />
<!-- BgLog结束 -->
</div>
</template>
<script>
import PopOverWithIcon from './components/SubOperators/PopOverWithIcon.vue'
import BetaGammaDetailedInfomation from './components/SubOperators/BetaGammaDetailedInfomation.vue'
import BetaGammaQcFlags from './components/SubOperators/BetaGammaQcFlags.vue'
import CustomSelect from '@/components/CustomSelect/index.vue'
import BetaGammaChartContainer from './components/BetaGammaChartContainer.vue'
import ResultDisplayBeta from './components/ResultDisplay-Beta.vue'
import BetaGammaSpectrum from './components/BetaGammaSpectrum.vue'
import RoiLimits from './components/RoiLimits/RoiLimits.vue'
import RoiParam from './components/RoiParam.vue'
import axios from 'axios'
import store from '@/store/'
import { getAction, postAction, putAction } from '../../api/manage'
import { addSampleData, getSampleData, updateSampleData } from '@/utils/SampleStore'
import { cloneDeep } from 'lodash'
import GammaModal from './components/Modals/SelfStation/GammaModal.vue'
import BetaModal from './components/Modals/SelfStation/BetaModal.vue'
import SelfStationArrRrrModal from './components/Modals/SelfStation/SelfStationArrRrrModal.vue'
import SelfStationSpectrumModal from './components/Modals/SelfStation/SelfStationSpectrumModal.vue'
import SelfStationPeakInfomation from './components/Modals/SelfStation/SelfStationPeakInfomation.vue'
import SelfStationAutomaticAnalysisLogModal from './components/Modals/SelfStation/SelfStationAutomaticAnalysisLogModal.vue'
import SelfStationBgLogViewer from './components/Modals/SelfStation/SelfStationBGLogViewer.vue'
const SampleType = [
{
label: 'Sample Data',
value: 'sample',
},
{
label: 'DetBg Data',
value: 'det',
},
{
label: 'QC Data',
value: 'qc',
},
]
const InitialRoiParamList = new Array(4).fill([0, 0])
const ROIColors = ['#16d5e6', '#34a1ff', '#66e411', '#fdaa1a']
export default {
components: {
PopOverWithIcon,
BetaGammaDetailedInfomation,
BetaGammaQcFlags,
CustomSelect,
BetaGammaChartContainer,
ResultDisplayBeta,
BetaGammaSpectrum,
RoiLimits,
RoiParam,
GammaModal,
BetaModal,
SelfStationArrRrrModal,
SelfStationSpectrumModal,
SelfStationPeakInfomation,
SelfStationAutomaticAnalysisLogModal,
SelfStationBgLogViewer,
},
props: {
sample: {
type: Object,
},
sampleList: {
type: Array,
default: () => [],
},
},
data() {
this.SampleType = SampleType
this.ROIColors = ROIColors
return {
currSpectrum: 'Sample',
isLoading: false,
spectrumData: {}, // Detailed Infomation 信息
spectraType: 'sample',
gammaEnergyData: [],
betaEnergyData: [],
ROILists: [],
ROIAnalyzeLists: [],
roiParamList: cloneDeep(InitialRoiParamList),
sampleDetail: {},
resultDisplay: [],
timerStamp: Date.now(),
}
},
watch: {
sample: {
async handler(newVal, oldVal) {
const sampleData = getSampleData(newVal.inputFileName)
if (sampleData) {
const { data } = sampleData
this.sampleDetail = data
this.changeChartByType('sample')
} else {
if (newVal.sampleId) {
this.getDetailFromDB()
} else {
this.getDetailFromFile()
}
this.ROIAnalyzeLists = []
}
},
immediate: true,
deep: true,
},
},
created() {
this.$bus.$on('selfRefresh', this.handleRefresh)
this.$bus.$on('selfAccept', this.handleAccept)
},
beforeDestroy() {
this.cancelLastRequest()
this.$bus.$on('selfRefresh', this.handleRefresh)
this.$bus.$off('selfAccept', this.handleAccept)
},
methods: {
// 从分析或来自db的谱信息拿到分析结果列表
getROIAnalyzeListsFromResult(sampleData) {
const arr = []
for (let index = 1; index <= 4; index++) {
const k = `ROI${index}`
arr.push(sampleData[k])
}
return arr
},
// 分析当前谱
async getAnalyzeCurrentSpectrum() {
if (this.isLoading) {
return
}
try {
const { inputFileName } = this.sample
const userId = store.getters.userInfo.id
this.isLoading = true
const formData = new FormData()
formData.append('fileName', inputFileName)
formData.append('processKey', `${userId}_${this.timerStamp}`)
const { success, result, message } = await postAction('/selfStation/Reprocessing', formData)
if (success) {
const analyseList = this.getROIAnalyzeListsFromResult(result)
this.ROIAnalyzeLists = this.spectraType == 'sample' ? analyseList : []
updateSampleData({
inputFileName,
key: 'ROIAnalyzeLists',
data: analyseList,
})
this.resultDisplay = result.XeData
} else {
const arr = message.split('\n')
this.$warning({
title: 'Warning',
content: () => arr.map((text) => <div>{text}</div>),
})
}
} catch (error) {
console.error(error)
} finally {
this.isLoading = false
}
},
// 分析全部
getAnalyzeAllSpectrum() {
this.$message.warning('尚未实现该功能')
},
// 点击Update
async handleUpdate() {
const hasEmpty = this.roiParamList.some(
([startChannel, endChannel]) => (!startChannel && startChannel != '0') || (!endChannel && endChannel != '0')
)
if (hasEmpty) {
this.$message.warning('Channel cannot be null')
return
}
const hasNegative = this.roiParamList.some(([startChannel, endChannel]) => startChannel < 0 || endChannel < 0)
if (hasNegative) {
this.$message.warning('Channel cannot be negative')
return
}
try {
this.isLoading = true
const params = this.roiParamList.map(([startChannel, endChannel], index) => ({
startChannel,
endChannel,
roiNum: index + 1,
}))
const { inputFileName } = this.sample
const userId = store.getters.userInfo.id
const formData = new FormData()
formData.append('roiParams', JSON.stringify(params))
formData.append('fileName', inputFileName)
formData.append('processKey', `${userId}_${this.timerStamp}`)
const { success, result, message } = await postAction('/selfStation/Reprocessing', formData)
if (success) {
for (let index = 0; index < 4; index++) {
const key = `ROI${index + 1}`
const value = result[key]
if (value) {
this.$set(this.ROIAnalyzeLists, index, value)
}
}
updateSampleData({
inputFileName,
key: 'ROIAnalyzeLists',
data: cloneDeep(this.ROIAnalyzeLists),
})
this.$refs.betaChartRef.setBoundaryList(cloneDeep(this.roiParamList))
const updateKeys = ['One', 'Two', 'Three', 'Four']
updateKeys.forEach((updateKey, index) => {
const innerKeys = ['Start', 'Stop']
innerKeys.forEach((innerKey, ind) => {
const realKey = `ROI${updateKey}${innerKey}`
updateSampleData({
inputFileName,
key: `sample.${realKey}`,
data: this.roiParamList[index][ind],
})
})
})
} else {
this.isLoading = false
const arr = message.split('\n')
this.$warning({
title: 'Warning',
content: () => arr.map((text) => <div>{text}</div>),
})
}
} catch (error) {
console.error(error)
} finally {
this.isLoading = false
}
},
async getDetailFromFile() {
this.spectraType = this.SampleType[0].value
const { inputFileName, detFileName, qcFileName } = this.sample
let params = {
sampleFileName: inputFileName,
detFileName: detFileName,
qcFileName: qcFileName,
}
try {
this.isLoading = true
this.cancelLastRequest()
const cancelToken = this.createCancelToken()
const { success, result, message } = await getAction('/selfStation/loadFromFile', params, cancelToken)
if (success) {
addSampleData({
inputFileName,
data: result,
from: 'file',
})
this.sampleDetail = result
this.changeChartByType('sample')
this.isLoading = false
} else {
this.$message.error(message)
this.isLoading = false
}
} catch (error) {
console.error(error)
const isCancel = axios.isCancel(error)
if (!isCancel) {
this.isLoading = false
}
}
},
// 获取谱详情
async getDetailFromDB() {
const { dbName, sampleId, analyst, inputFileName } = this.sample
try {
this.cancelLastRequest()
this.isLoading = true
const cancelToken = this.createCancelToken()
const { success, result, message } = await getAction(
'/selfStation/loadFromDB',
{
dbName,
sampleId,
analyst,
},
cancelToken
)
if (success) {
addSampleData({
inputFileName,
data: result,
from: 'db',
})
const analyseList = this.getROIAnalyzeListsFromResult(result.sample)
updateSampleData({
inputFileName,
key: 'ROIAnalyzeLists',
data: analyseList,
})
this.sampleDetail = result
this.changeChartByType('sample')
this.isLoading = false
} else {
this.$message.error(message)
this.isLoading = false
}
} catch (error) {
console.error(error)
const isCancel = axios.isCancel(error)
if (!isCancel) {
this.isLoading = false
}
}
},
changeChartByType(val) {
const currSampleDetail = this.sampleDetail[this.spectraType]
if (!currSampleDetail) {
this.$message.warning(`No ${this.spectraType} spectrum file!`)
this.$nextTick(() => {
this.spectraType = this.prevSpectraType
})
return
}
this.prevSpectraType = val
if (val == 'sample') {
this.currSpectrum = 'Sample'
this.ROIAnalyzeLists = this.sampleDetail.ROIAnalyzeLists || []
} else {
this.ROIAnalyzeLists = []
}
if (val == 'detBg') this.currSpectrum = 'Det'
if (val == 'qc') this.currSpectrum = 'QC'
this.roiParamList = cloneDeep(InitialRoiParamList)
this.ROILists = []
const {
spectrumData,
betaEnergyData,
gammaEnergyData,
histogramDataList,
ROIOneList,
ROITwoList,
ROIThreeList,
ROIFourList,
ROIOneStart,
ROIOneStop,
ROITwoStart,
ROITwoStop,
ROIThreeStart,
ROIThreeStop,
ROIFourStart,
ROIFourStop,
} = currSampleDetail
this.spectrumData = spectrumData
const boundaryList = [
[ROIOneStart, ROIOneStop],
[ROITwoStart, ROITwoStop],
[ROIThreeStart, ROIThreeStop],
[ROIFourStart, ROIFourStop],
]
this.roiParamList = cloneDeep(boundaryList)
this.$nextTick(() => {
this.$refs.betaChartRef.setBoundaryList(boundaryList)
this.$refs.betaChartRef.setData(histogramDataList)
})
this.gammaEnergyData = gammaEnergyData
this.betaEnergyData = betaEnergyData
this.ROILists = [ROIOneList, ROITwoList, ROIThreeList, ROIFourList]
this.$bus.$emit('selfAnalyzeSampleTypeChange', val)
},
cancelLastRequest() {
if (this._cancelToken && typeof this._cancelToken == 'function') {
this._cancelToken()
}
},
createCancelToken() {
const cancelToken = new axios.CancelToken((c) => {
this._cancelToken = c
})
return cancelToken
},
handleGetFlag(val, obj) {
this.resultDisplay.forEach((item) => {
if (item.nuclideName === obj.nuclideName) {
item.nidFlag = val ? 1 : 0
}
})
},
resize() {},
// 矩形框范围改变
handleBoundaryChange(evt) {
const { index, start, end } = evt
this.$set(this.roiParamList, index, [start, end])
this.$refs.betaChartRef.setBoundaryList(cloneDeep(this.roiParamList))
},
// 从分析工具刷新部分数据
handleRefresh(data, index) {
this.ROIAnalyzeLists[index] = this.$set(this.ROIAnalyzeLists, index, data)
const { inputFileName } = this.sample
updateSampleData({
inputFileName,
key: 'ROIAnalyzeLists',
data: this.ROIAnalyzeLists,
})
},
// 分析工具Accept时刷新部分数据
handleAccept(data, index) {
const {
allData,
peak,
shadowChannelChart,
shadowEnergyChart,
shapeChannelData,
shapeEnergyData,
barChart,
BaseCtrls,
} = data
this.ROIAnalyzeLists[index] = this.$set(this.ROIAnalyzeLists, index, {
allData,
peak,
shadowChannelChart,
shadowEnergyChart,
shapeChannelData,
shapeEnergyData,
barChart,
BaseCtrls,
})
const { inputFileName } = this.sample
updateSampleData({
inputFileName,
key: 'ROIAnalyzeLists',
data: this.ROIAnalyzeLists,
})
},
// 打开Gamma或Beta弹窗
handleOpenModal(index) {
const currSampleDetail = this.sampleDetail[this.spectraType]
if (!currSampleDetail) {
this.$message.warning(`No ${this.spectraType} spectrum file!`)
return
}
if (index == 0) {
this.$refs.gammaModalRef.open(currSampleDetail.gSpectrum, currSampleDetail.gammaEnergyData)
} else if (index == 1) {
this.$refs.betaModalRef.open(currSampleDetail.bSpectrum, currSampleDetail.betaEnergyData)
}
},
// 保存当前谱到db
async saveCurrentToDB() {
if (!this.ROIAnalyzeLists || !this.ROIAnalyzeLists.length) {
throw new Error('Please Analyse Spectrum First')
}
const { inputFileName: fileName } = this.sample
const { success, message, result } = await getAction('/selfStation/saveToDB', {
fileName,
})
if (success) {
Object.entries(result).forEach(([k, v]) => {
// 更新缓存中的DetailedInfomation数据
updateSampleData({
inputFileName: fileName,
key: `${k}.spectrumData`,
data: v,
})
})
this.spectrumData = result[this.spectraType]
} else {
throw new Error(message)
}
},
// 显示ARR或RRR弹窗
showArrRRRModal(type) {
this.$refs.ARR_RRRModalRef.show(type)
},
showSpectrumModal() {
this.$refs.spectrumModalRef.show()
},
showPeakInfoModal() {
this.$refs.peakInfoModalRef.show()
},
showAutomaticAnalysisLog() {
this.$refs.autoAnalysisLogRef.show()
},
showBgLogViewer() {
this.$refs.bgLogViewerRef.show()
},
},
}
</script>
<style lang="less" scoped>
.beta-gamma-analysis {
height: 100%;
.ant-spin-nested-loading {
height: 100%;
::v-deep {
.ant-spin-container {
height: 100%;
}
}
}
.sample-select {
::v-deep {
.ant-select-selection {
background-color: transparent !important;
color: #ade6ee;
}
}
}
&-main {
height: calc(100% - 65px);
display: flex;
gap: 30px;
overflow: auto hidden;
&-left {
flex: 768;
}
&-right {
flex: 1068;
.betagamma-chart {
height: calc(100% - 200px);
}
}
&-bottom {
height: 194px;
overflow: auto hidden;
&-left {
flex: 1;
}
&-right {
flex: 1;
}
}
}
}
// 二级操作栏开始
.spectrum-analysis-sub-operators {
flex-shrink: 0;
margin-bottom: 19px;
display: flex;
gap: 11px;
flex-wrap: nowrap;
overflow: auto;
height: 46px;
align-items: center;
font-family: Microsoft Yahei;
.pop-over-with-icon {
height: 32px;
flex-shrink: 0;
&:nth-child(1) {
width: 224px;
}
&:nth-child(3) {
width: 125px;
}
}
&-roi {
display: flex;
align-items: center;
&-name {
padding: 5px 10px;
}
.ant-input-group {
display: flex;
background-color: #04414d;
border: solid 1px #0b8c82;
}
&-input {
width: 80px;
text-align: center;
border: 0;
background: transparent;
}
&-split {
width: 5px;
}
}
&-button {
text-align: center;
height: 32px;
line-height: 32px;
min-width: 94px;
padding: 0 10px;
font-size: 16px;
margin-left: 16px;
cursor: pointer;
&[disabled] {
color: #fff;
background-color: #1397a3;
cursor: not-allowed;
}
}
}
// 二级操作栏结束
</style>