AnalysisSystemForRadionucli.../src/views/spectrumAnalysis/components/Modals/EfficiencyCalibrationModal.vue

640 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<custom-modal v-model="visible" :width="1280" title="Efficiency Calibration" :footer="null" destroy-on-close>
<a-spin :spinning="isLoading">
<div class="energy-calibration">
<div class="left">
<!-- Calibration Data -->
<title-over-border title="Calibration Data">
<div class="calibration-data">
<a-form-model
:colon="false"
:labelCol="{
style: {
width: '70px',
textAlign: 'left',
flexShrink: 0
}
}"
:wrapperCol="{
style: {
flex: 1
}
}"
>
<a-form-model-item label="Energy">
<a-input type="number" v-model="model.energy"></a-input>
</a-form-model-item>
<a-form-model-item label="Efficiency">
<a-input type="number" v-model="model.efficiency"></a-input>
</a-form-model-item>
<a-form-model-item :label="' '">
<a-button type="primary" @click="handleInsert">Insert</a-button>
</a-form-model-item>
<a-form-model-item :label="' '">
<a-button type="primary" @click="handleModify">Modify</a-button>
</a-form-model-item>
<a-form-model-item :label="' '">
<a-button type="primary" @click="handleDelete">Delete</a-button>
</a-form-model-item>
</a-form-model>
<!-- 表格 -->
<custom-table
:columns="columns"
:list="list"
:pagination="false"
size="small"
:class="list.length ? 'has-data' : ''"
:scroll="{ y: 182 }"
:selectedRowKeys.sync="selectedRowKeys"
:canDeselect="false"
@rowClick="handleRowClick"
></custom-table>
<!-- 表格结束 -->
<div class="operators">
<div>
<a-button type="primary">Call</a-button>
<a-button type="primary">Save</a-button>
</div>
<div>
<a-select v-model="funcId" @change="recalculate">
<a-select-option v-for="(func, index) in functions" :key="index" :value="func.value">
{{ func.label }}
</a-select-option>
</a-select>
<a-button type="primary" @click="handleApply">Apply</a-button>
</div>
</div>
</div>
</title-over-border>
<!-- Equation -->
<title-over-border class="mt-20" title="Equation">
<div class="equation" v-html="equation"></div>
</title-over-border>
<!-- curve -->
<title-over-border class="mt-20" title="curve">
<div class="curve">
<custom-chart :option="option" :opts="opts" />
</div>
</title-over-border>
</div>
<div class="right">
<title-over-border title="Data Source" style="height: 100%">
<div class="data-source">
<div class="content">
<div
class="item"
:class="item == currSelectedDataSource ? 'active' : ''"
v-for="(item, index) in dataSourceList"
:key="index"
@click="handleDataSourceClick(item)"
>
{{ item }}
</div>
</div>
<div class="footer mt-20">
<a-button type="primary" @click="handleSetToCurrent">Set to Current</a-button>
<div class="mt-20">{{ appliedDataSource }}</div>
</div>
</div>
</title-over-border>
</div>
</div>
</a-spin>
</custom-modal>
</template>
<script>
import ModalMixin from '@/mixins/ModalMixin'
import TitleOverBorder from '../TitleOverBorder.vue'
import CustomChart from '@/components/CustomChart/index.vue'
import { getAction, postAction } from '@/api/manage'
import { cloneDeep } from 'lodash'
import { buildLineSeries } from '@/utils/chartHelper'
import SampleDataMixin from '../../SampleDataMixin'
const columns = [
{
title: 'Energy(keV)',
dataIndex: 'energy'
},
{
title: 'Efficiency',
dataIndex: 'efficiency'
},
{
title: 'Fit(keV)',
dataIndex: 'fit'
},
{
title: 'Delta(%)',
dataIndex: 'delta'
}
]
const initialOption = {
grid: {
top: 20,
right: 20,
bottom: 50,
left: 70
},
title: {
text: 'Channel',
textStyle: {
color: '#8FD4F8',
fontSize: 14,
fontWeight: 'normal'
},
right: 10,
bottom: 0
},
tooltip: {
trigger: 'axis',
formatter: params => {
const [x, y] = params[0].value
const energy = parseInt(x)
const efficiency = y.toFixed(3)
return `<div class="channel">Energy: ${energy}</div>
<div class="energy">Efficiency: ${efficiency}</div>`
},
className: 'figure-chart-option-tooltip'
},
xAxis: {
min: 1,
max: 'dataMax',
axisLabel: {
color: '#fff'
},
axisLine: {
lineStyle: {
color: '#fff'
}
},
splitLine: {
show: false
}
},
yAxis: {
axisLabel: {
color: '#fff'
},
axisTick: {
show: false
},
axisLine: {
lineStyle: {
color: '#fff'
}
},
splitLine: {
show: false
},
name: 'keV',
nameLocation: 'center',
nameGap: 50,
nameTextStyle: {
color: '#8FD4F8',
fontSize: 14
}
},
series: []
}
const functions = [
{
label: 'Interpolation',
value: 1
},
{
label: 'HT Efficiency',
value: 5
},
{
label: 'Log Polynomial',
value: 6
},
{
label: 'Invlog Polynomial',
value: 8
},
{
label: 'HAE Efficiency(1-3)',
value: 93
},
{
label: 'HAE Efficiency(1-2)',
value: 94
},
{
label: 'HAE Efficiency(1-2-3)',
value: 95
}
]
export default {
components: { TitleOverBorder, CustomChart },
mixins: [ModalMixin, SampleDataMixin],
data() {
this.columns = columns
this.functions = functions
return {
isLoading: false,
equation: '',
dataSourceList: [],
list: [],
option: cloneDeep(initialOption),
selectedRowKeys: [],
model: {},
currSelectedDataSource: '',
appliedDataSource: '',
opts: {
notMerge: true
},
ECutAnalysis_Low: -1,
G_energy_span: -1,
funcId: 1
}
},
methods: {
async getData(currentText) {
try {
this.isLoading = true
const { sampleId, inputFileName: fileName } = this.sampleData
const { success, result, message } = await getAction('/gamma/EfficiencyCalibration', {
sampleId,
fileName,
currentText
})
this.isLoading = false
if (success) {
console.log('%c [ ]-220', 'font-size:13px; background:pink; color:#bf2c9f;', result)
const { list_dataSource, ECutAnalysis_Low, G_energy_span } = result
this.dataSourceList = list_dataSource
if (!currentText) {
this.currSelectedDataSource = list_dataSource[list_dataSource.length - 1]
this.appliedDataSource = list_dataSource[list_dataSource.length - 1]
}
this.ECutAnalysis_Low = ECutAnalysis_Low
this.G_energy_span = G_energy_span
this.handleResult(result)
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
}
},
handleResult(result) {
const { AllData, equation, param, table, uncert } = result
// 有数据
if (AllData) {
const [linePoint, scatterPoint] = AllData
this.equation = equation
this.param = param
this.uncert = uncert
this.list = table
this.generateTableId()
const series = []
series.push(
buildLineSeries(
'LineSeries',
linePoint.pointlist.map(({ x, y }) => [x, y]),
`rgb(${linePoint.color})`
)
)
series.push({
type: 'scatter',
data: scatterPoint.pointlist.map(({ x, y }) => {
return {
value: [x, y],
itemStyle: {
color: scatterPoint.color,
borderWidth: 0
}
}
}),
emphasis: {
disabled: true
},
animation: false,
zlevel: 20
})
this.option.series = series
}
// 没数据
else {
this.option.series = []
}
},
beforeModalOpen() {
this.selectedRowKeys = []
this.funcId = 1
this.getData()
},
// 表格单行点击
handleRowClick(row) {
this.model = cloneDeep(row)
},
// 插入
handleInsert() {
const energy = parseFloat(this.model.energy)
const efficiency = parseFloat(this.model.efficiency)
if (Number.isNaN(energy) || Number.isNaN(efficiency)) {
this.$message.warn('Format is invalid.')
return
}
if (energy <= this.ECutAnalysis_Low || energy >= this.G_energy_span) {
this.$message.warn('Energy is out of analysis range.')
return
}
let i,
num = this.list.length
for (i = 0; i < num; ++i) {
const currEnergy = this.list[i].energy
if (Math.abs(currEnergy - energy) < 0.001) {
this.$message.warn('The centroid has already existed!')
return
} else if (currEnergy > energy) {
break
}
}
this.list.splice(i, 0, {
energy: energy,
efficiency
})
this.uncert.splice(i, 0, 0.5)
this.selectedRowKeys = [i]
this.generateTableId()
this.recalculate()
},
// 生成table中数据的id用以选中
generateTableId() {
this.list.forEach((item, index) => {
item.id = index
})
},
// 修改
handleModify() {
if (this.selectedRowKeys.length) {
const energy = parseFloat(this.model.energy)
const efficiency = parseFloat(this.model.efficiency)
if (Number.isNaN(energy) || Number.isNaN(efficiency)) {
this.$message.warn('Format is invalid.')
return
}
if (energy <= this.ECutAnalysis_Low || energy >= this.G_energy_span) {
this.$message.warn('Energy is out of analysis range.')
return
}
const [currSelectedIndex] = this.selectedRowKeys
this.list[currSelectedIndex].energy = energy
this.list[currSelectedIndex].efficiency = efficiency
this.uncert[currSelectedIndex] = 0
this.recalculate()
}
},
// 删除
handleDelete() {
if (this.selectedRowKeys.length) {
const [currSelectedIndex] = this.selectedRowKeys
this.list.splice(currSelectedIndex, 1)
this.uncert.splice(currSelectedIndex, 1)
this.generateTableId()
if (this.list.length) {
const selectedKey = this.selectedRowKeys[0]
if (selectedKey > this.list.length - 1) {
this.selectedRowKeys[0] = selectedKey - 1
}
} else {
this.selectedRowKeys = []
}
this.recalculate()
}
},
// 重新计算
async recalculate() {
try {
this.isLoading = true
const { sampleId, inputFileName: fileName } = this.sampleData
const { success, result, message } = await postAction('/gamma/changeDataEfficiency', {
sampleId,
fileName,
m_vCurEnergy: this.list.map(item => item.energy),
m_vCurEffi: this.list.map(item => item.efficiency),
m_vCurUncert: this.uncert,
m_curParam: this.param,
funcId: this.funcId
})
if (success) {
this.handleResult(result)
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
} finally {
this.isLoading = false
}
},
// 应用
async handleApply() {
try {
let curCalName = this.currSelectedDataSource
// 如果沒选中以Input开头的也就是选中了PHD之类的
if (!curCalName.includes('Input')) {
curCalName = `Input ${this.dataSourceList.filter(item => item.includes('Input')).length + 1}`
}
const { sampleId, inputFileName: fileName } = this.sampleData
const { success, result, message } = await postAction('/gamma/applyDataEfficiency', {
m_vCurEnergy: this.list.map(item => item.energy),
m_vCurEffi: this.list.map(item => item.efficiency),
m_vCurUncert: this.uncert,
m_curParam: this.param,
curCalName,
sampleId,
fileName
})
if (success) {
this.handleDataSourceClick(curCalName)
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
}
},
// 右侧DataSource中的选项点击
handleDataSourceClick(item) {
this.currSelectedDataSource = item
this.getData(item)
},
handleSetToCurrent() {
this.appliedDataSource = this.currSelectedDataSource
}
}
}
</script>
<style lang="less" scoped>
.energy-calibration {
display: flex;
margin-top: 5px;
.left {
flex: 1;
.calibration-data {
display: flex;
gap: 20px;
.ant-form {
width: 25%;
::v-deep {
.ant-form-item {
margin-bottom: 15px;
&-label,
&-control {
line-height: 32px;
}
&:last-child {
margin-bottom: 0;
}
}
}
.ant-btn {
width: 100%;
}
}
.ant-table-wrapper {
width: 50%;
&.has-data {
::v-deep {
.ant-table-body {
height: 182px;
background-color: #06282a;
}
}
}
::v-deep {
.ant-table-placeholder {
height: 183px;
display: flex;
justify-content: center;
align-items: center;
}
}
}
.operators {
width: 25%;
display: flex;
flex-direction: column;
justify-content: space-between;
.ant-select {
width: 100%;
}
.ant-btn {
width: 100%;
&:last-child {
margin-top: 10px;
}
}
}
}
.equation {
height: 40px;
background-color: #1b5465;
display: flex;
justify-content: center;
align-items: center;
}
.curve {
height: 400px;
}
}
.right {
width: 20%;
margin-left: 20px;
.data-source {
.content {
height: 330px;
background-color: #275466;
overflow: auto;
.item {
height: 32px;
line-height: 32px;
padding: 0 5px;
cursor: pointer;
&.active {
background-color: #296d81;
}
}
}
.footer {
.ant-btn {
width: 100%;
}
> div {
text-align: center;
height: 32px;
line-height: 32px;
background-color: #285367;
}
}
}
}
}
.mt-20 {
margin-top: 20px;
}
</style>