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

1413 lines
41 KiB
Vue
Raw Normal View History

2023-06-28 19:25:11 +08:00
<template>
<div class="gamma-analysis">
<a-spin :spinning="isLoading">
<!-- 二级交互栏 -->
<div class="spectrum-analysis-sub-operators">
<pop-over-with-icon placement="bottomLeft">
Detailed-Information
<detailed-infomation slot="content" :data="detailedInfomation" />
</pop-over-with-icon>
<pop-over-with-icon placement="bottomLeft">
QC Flags
<qc-flags slot="content" :data="qcFlags" />
</pop-over-with-icon>
<pop-over-with-icon>
Graph Assistance
<graph-assistance
v-if="!isLoading"
slot="content"
@change="handleGraphAssistanceChange"
@reset="handleResetChart"
/>
</pop-over-with-icon>
<a-popover
overlayClassName="popover-with-icon"
:visible="nuclideLibraryVisible"
@click="handleChangeNuclideVisible"
placement="bottom"
>
<div class="pop-over-with-icon">
<span class="text"> Nuclide Library </span>
<img src="@/assets/images/global/select-down.png" alt="" />
</div>
<a-spin slot="content" :spinning="isLoadingNuclide">
<nuclide-library :list="nuclideLibraryList" @dblclick="handleNuclideDblClick" />
</a-spin>
</a-popover>
<div class="peak-info">
<button-with-switch-icon @change="handlePeakInfoChange" @click="handleTogglePeak"></button-with-switch-icon>
</div>
</div>
<!-- 二级交互栏结束 -->
<!-- 主体部分 -->
<div class="gamma-analysis-main">
<div class="gamma-analysis-chart">
<CustomChart
ref="chartRef"
:option="option"
:opts="opts"
@zr:click="handleChartClick"
@zr:dblclick="handleChartDblClick"
@zr:mousedown="handleMouseDown"
@zr:mouseup="handleMouseUp"
@brushEnd="handleBrushEnd"
style="height: 100%"
/>
<!-- 右上角缩略图 -->
<div class="gamma-analysis-thumbnail">
<CustomChart
ref="thumbnailChartRef"
:option="thumbnailOption"
@zr:click="handleThumbnailChartClick"
style="height: 100%"
/>
</div>
<!-- 缩略图结束 -->
<!-- 自定义tooltip用于展示Peak Infomation -->
<div
v-if="peakInfomationTooltip.visible"
class="peak-infomation-tooltip"
:style="{
top: peakInfomationTooltip.top + 'px',
left: peakInfomationTooltip.left + 'px',
}"
>
<div class="peak-infomation-tooltip-content" v-html="peakInfomationTooltip.content"></div>
</div>
<!-- tooltip结束 -->
</div>
</div>
<!-- 主体部分结束 -->
</a-spin>
<nuclide-review-modal
v-model="nuclideReview.visible"
:sampleId="sample.sampleId"
:channel="currChannel"
:nuclide="nuclideReview.nuclide"
/>
<compare-file-list-modal v-model="compareFileListModalVisible" @compareWithFile="handleCompareWithFile" />
<!-- ReProcessing 弹窗开始 -->
<re-processing-modal v-model="reprocessingModalVisible" />
<!-- ReProcessing 弹窗结束 -->
2023-06-28 19:25:11 +08:00
</div>
</template>
<script>
import CustomChart from '@/components/CustomChart/index.vue'
import PopOverWithIcon from './components/SubOperators/PopOverWithIcon.vue'
import DetailedInfomation from './components/SubOperators/DetailedInfomation.vue'
import QcFlags from './components/SubOperators/QcFlags.vue'
import GraphAssistance from './components/SubOperators/GraphAssistance.vue'
import NuclideLibrary from './components/SubOperators/NuclideLibrary.vue'
import ButtonWithSwitchIcon from './components/SubOperators/ButtonWithSwitchIcon.vue'
import { getAction, postAction } from '@/api/manage'
import Response from './response.json'
import {
buildLineSeries,
findSeriesByName,
getAxisMax,
getXAxisAndYAxisByPosition,
rangeNumber,
} from '@/utils/chartHelper'
import { cloneDeep } from 'lodash'
import axios from 'axios'
import NuclideReviewModal from './components/Modals/AnalyzeInteractiveToolModal/components/NuclideReviewModal.vue'
import CompareFileListModal from './components/Modals/CompareFileListModal.vue'
import ReProcessingModal from './components/Modals/ReProcessingModal/index.vue'
2023-06-28 19:25:11 +08:00
2023-09-27 13:41:51 +08:00
import { GammaOptions, graphAssistance } from './settings'
2023-06-28 19:25:11 +08:00
export default {
props: {
sample: {
type: Object,
},
2023-06-28 19:25:11 +08:00
},
components: {
CustomChart,
PopOverWithIcon,
DetailedInfomation,
QcFlags,
GraphAssistance,
NuclideLibrary,
ButtonWithSwitchIcon,
NuclideReviewModal,
CompareFileListModal,
ReProcessingModal,
2023-06-28 19:25:11 +08:00
},
data() {
return {
isLoading: false,
isLoadingNuclide: false,
2023-09-27 13:41:51 +08:00
option: cloneDeep(GammaOptions.option),
opts: {
notMerge: false,
},
2023-09-27 13:41:51 +08:00
thumbnailOption: cloneDeep(GammaOptions.thumbnailOption),
detailedInfomation: [],
qcFlags: [],
graphAssistance: cloneDeep(graphAssistance),
nuclideLibraryVisible: false,
2023-09-27 13:41:51 +08:00
channelData: {
peakGroup: [],
spectrumLine: null,
baseLine: null,
lcLine: null,
scacLine: null,
all: null,
baseLineCP: [],
},
energyData: {
peakGroup: [],
spectrumLine: null,
baseLine: null,
lcLine: null,
scacLine: null,
all: null,
baseLineCP: [],
},
nuclideLibraryList: [], // 当前鼠标点击选中的channel
peakInfomationTooltip: {
// Peak Infomation的位置
visible: false,
content: '',
top: 0,
left: 0,
},
nuclideReview: {
visible: false,
nuclide: '',
},
currChannel: -1,
compareFileListModalVisible: false, // Compare 弹窗
reprocessingModalVisible: false, // 重新分析弹窗
isProcessing: false, // 正在处理
2023-06-28 19:25:11 +08:00
}
},
created() {
this.option.title.text = '{a|Channel:0} {a|Energy:0} {a|Counts:0} {a|Detectability:0}'
2023-09-27 13:41:51 +08:00
this.option.tooltip.formatter = this.tooltipFormatter
this.$bus.$on('colorChange', this.handleColorChange)
this.$bus.$on('gammaRefresh', this.handleRefresh)
this.$bus.$on('accept', this.handleAccept)
},
destroyed() {
2023-09-27 14:53:17 +08:00
this.cancelLastRequest()
this.$bus.$off('colorChange', this.handleColorChange)
this.$bus.$off('gammaRefresh', this.handleRefresh)
this.$bus.$off('accept', this.handleAccept)
2023-06-28 19:25:11 +08:00
},
mounted() {
this.option.brush = { toolbox: [] }
},
2023-06-28 19:25:11 +08:00
methods: {
2023-09-27 13:41:51 +08:00
// 获取样品详情
async getSampleDetail() {
const { dbName, sampleId } = this.sample
try {
this.isLoading = true
this.handleResetState()
// const { success, result, message } = Response
2023-09-27 14:53:17 +08:00
this.cancelLastRequest()
const cancelToken = this.createCancelToken()
const { success, result, message } = await getAction(
'/gamma/gammaByDB',
{
dbName,
sampleId,
},
cancelToken
)
console.log('%c [ result ]-243', 'font-size:13px; background:pink; color:#bf2c9f;', result)
if (success) {
this.dataProsess(result)
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
}
},
2023-09-11 11:01:23 +08:00
async getSampleDetail_file() {
const { inputFileName: fileName } = this.sample
try {
this.isLoading = true
this.handleResetState()
2023-09-11 11:01:23 +08:00
// const { success, result, message } = Response
2023-09-27 14:53:17 +08:00
this.cancelLastRequest()
const cancelToken = this.createCancelToken()
2023-09-27 13:41:51 +08:00
const { success, result, message } = await getAction(
'/gamma/gammaByFile',
{
fileName,
},
cancelToken
)
2023-09-11 11:01:23 +08:00
console.log('%c [ result ]-243', 'font-size:13px; background:pink; color:#bf2c9f;', result)
if (success) {
this.dataProsess(result)
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
}
},
2023-09-11 11:01:23 +08:00
2023-09-27 13:41:51 +08:00
cancelLastRequest() {
if (this._cancelToken && typeof this._cancelToken == 'function') {
this._cancelToken()
}
2023-09-27 14:53:17 +08:00
},
2023-09-27 13:41:51 +08:00
2023-09-27 14:53:17 +08:00
createCancelToken() {
const cancelToken = new axios.CancelToken((c) => {
2023-09-27 13:41:51 +08:00
this._cancelToken = c
})
2023-09-27 14:53:17 +08:00
return cancelToken
2023-09-27 13:41:51 +08:00
},
dataProsess(result) {
this.isLoading = false
const {
dead_time,
live_time,
real_time,
start_time,
DetailedInformation,
QCFlag,
allData,
shadowChannelChart,
shadowEnergyChart,
shapeChannelData,
shapeEnergyData,
} = result
this.detailedInfomation = DetailedInformation
this.qcFlags = QCFlag
2023-09-27 13:41:51 +08:00
const channelPeakGroup = this.getLineData(allData, 'Peak', 'channel', true)
const energyPeakGroup = this.getLineData(allData, 'Peak', 'energy', true)
2023-09-27 13:41:51 +08:00
const channelBaseLine = this.getLineData(allData, 'BaseLine', 'channel')
const energyBaseLine = this.getLineData(allData, 'BaseLine', 'energy')
2023-09-27 13:41:51 +08:00
const channelLcLine = this.getLineData(allData, 'Lc', 'channel')
const energyLcLine = this.getLineData(allData, 'Lc', 'energy')
2023-09-27 13:41:51 +08:00
const channelScacLine = this.getLineData(allData, 'Scac', 'channel')
const energyScacLine = this.getLineData(allData, 'Scac', 'energy')
2023-09-27 13:41:51 +08:00
const allChannel = this.getLineData(allData, 'Count', 'channel')
const allEnergy = this.getLineData(allData, 'Energy', 'energy')
2023-09-27 13:41:51 +08:00
this.channelData = {
peakGroup: channelPeakGroup,
spectrumLine: shadowChannelChart,
baseLine: channelBaseLine,
lcLine: channelLcLine,
scacLine: channelScacLine,
all: allChannel,
baseLineCP: shapeChannelData,
}
2023-09-27 13:41:51 +08:00
this.energyData = {
peakGroup: energyPeakGroup,
spectrumLine: shadowEnergyChart,
baseLine: energyBaseLine,
lcLine: energyLcLine,
scacLine: energyScacLine,
all: allEnergy,
baseLineCP: shapeEnergyData,
}
this.resetThumbnailChartDataMax()
const series = []
// 推入Spectrum Line
series.push(
buildLineSeries(
'Spectrum',
2023-09-27 13:41:51 +08:00
this.transformPointListData(shadowChannelChart.pointlist),
shadowChannelChart.color,
{
symbolSize: 2,
markLine: {
silent: true,
symbol: 'none',
label: {
show: false,
},
lineStyle: {
color: 'red',
width: 1,
},
data: [{ xAxis: -1 }],
},
}
)
)
2023-09-11 11:01:23 +08:00
2023-09-27 13:41:51 +08:00
// 右上角缩略图设置Spectrum Line 数据
this.setSeriesData(
this.thumbnailOption.series,
'Spectrum',
this.transformPointListData(shadowChannelChart.pointlist),
shadowChannelChart.color
)
// 推入BaseLine
series.push(
2023-09-27 13:41:51 +08:00
buildLineSeries('BaseLine', this.transformPointListData(channelBaseLine.pointlist), channelBaseLine.color, {
zlevel: 2,
})
)
2023-09-11 11:01:23 +08:00
// 推入LcLine线
series.push(
2023-09-27 13:41:51 +08:00
buildLineSeries('LcLine', this.transformPointListData(channelLcLine.pointlist), channelLcLine.color, {
zlevel: 3,
})
)
2023-09-11 11:01:23 +08:00
// 推入Scac线
series.push(
2023-09-27 13:41:51 +08:00
buildLineSeries('ScacLine', this.transformPointListData(channelScacLine.pointlist), channelScacLine.color, {
zlevel: 4,
})
)
2023-09-11 11:01:23 +08:00
// 推入基线控制点
series.push({
name: 'BaseLine_Ctrl_Point',
type: 'scatter',
data: shapeChannelData.map(({ size, color, point: { x, y } }) => {
return {
value: [x, y],
2023-09-11 11:01:23 +08:00
itemStyle: {
color: 'transparent',
borderColor: color,
borderWidth: size / 2,
},
}
}),
emphasis: {
disabled: true,
},
animation: false,
zlevel: 5,
})
2023-09-11 11:01:23 +08:00
// 推入Peak Line
const peakLines = []
channelPeakGroup.forEach((item, index) => {
peakLines.push(
2023-09-27 13:41:51 +08:00
buildLineSeries(`Peak_${index}`, this.transformPointListData(item.pointlist), item.color, {
zlevel: 6,
})
)
})
series.push(...peakLines)
// 推入Compare Line
series.push(
buildLineSeries('Compare', [], '#fff', {
symbolSize: 2,
})
)
this.option.series = series
2023-09-11 11:01:23 +08:00
},
2023-09-27 13:41:51 +08:00
// chart 的 tooltip
tooltipFormatter(params) {
2023-09-27 13:41:51 +08:00
let channel = 0
let energy = 0
const value = params[0].value[0]
2023-09-27 13:41:51 +08:00
if (this.isEnergy()) {
energy = value.toFixed(2)
channel = this.getChannelByEnergy(energy)
} else {
2023-09-27 13:41:51 +08:00
const allPointList = this.energyData.all.pointlist
channel = parseInt(value.toFixed())
energy = allPointList && allPointList[channel - 1]
energy = energy ? energy.x.toFixed(2) : undefined
}
2023-09-27 13:41:51 +08:00
return `<div class="channel">Channel: ${channel}</div>
<div class="energy">Energy: ${energy}</div>`
},
// Graph Assistance 操作
handleGraphAssistanceChange({ type, label, value }) {
const spectrumLineSeries = findSeriesByName(this.option.series, 'Spectrum')
const thumbnailSpectrumLineSeries = findSeriesByName(this.thumbnailOption.series, 'Spectrum')
const compareLineSeries = findSeriesByName(this.option.series, 'Compare')
// 类型变化
if (type == 'labelChange') {
switch (label) {
case 'Linear':
this.option.yAxis.type = 'value'
this.thumbnailOption.yAxis.type = 'value'
this.handleResetChart()
break
case 'Log10':
this.option.yAxis.type = 'log'
this.thumbnailOption.yAxis.type = 'log'
this.handleResetChart()
break
case 'Channel':
case 'Energy':
this.graphAssistance.axisType = label
this.option.xAxis.name = label
this.handleResetChart()
this.redrawLineBySeriesName(
'BaseLine',
2023-09-27 13:41:51 +08:00
this.energyData.baseLine,
this.channelData.baseLine,
this.graphAssistance.Baseline
)
2023-09-27 13:41:51 +08:00
this.redrawLineBySeriesName(
'LcLine',
this.energyData.lcLine,
this.channelData.lcLine,
this.graphAssistance.Lc
)
this.redrawLineBySeriesName(
'ScacLine',
2023-09-27 13:41:51 +08:00
this.energyData.scacLine,
this.channelData.scacLine,
this.graphAssistance.SCAC
)
2023-09-27 13:41:51 +08:00
this.redrawLineBySeriesName('Spectrum', this.energyData.spectrumLine, this.channelData.spectrumLine)
this.redrawCtrlPointBySeriesName()
this.redrawPeakLine()
this.redrawThumbnailChart()
if (this.channelCompareLine) {
this.redrawLineBySeriesName('Compare', this.energyCompareLine, this.channelCompareLine)
}
break
case 'Lines':
this.graphAssistance.spectrumType = 'Lines'
spectrumLineSeries.type = 'line'
spectrumLineSeries.symbol = 'none'
thumbnailSpectrumLineSeries.type = 'line'
thumbnailSpectrumLineSeries.symbol = 'none'
compareLineSeries.type = 'line'
compareLineSeries.symbol = 'none'
2023-09-27 13:41:51 +08:00
this.redrawLineBySeriesName('Spectrum', this.energyData.spectrumLine, this.channelData.spectrumLine)
if (this.channelCompareLine) {
this.redrawLineBySeriesName('Compare', this.energyCompareLine, this.channelCompareLine)
}
break
case 'Scatter':
this.graphAssistance.spectrumType = 'Scatter'
spectrumLineSeries.type = 'scatterGL'
spectrumLineSeries.symbol = 'circle'
thumbnailSpectrumLineSeries.type = 'scatterGL'
thumbnailSpectrumLineSeries.symbol = 'circle'
compareLineSeries.type = 'scatterGL'
compareLineSeries.symbol = 'circle'
this.$nextTick(() => {
this.rangeScatter()
})
break
}
}
// 值变化
else if (type == 'valueChange') {
this.graphAssistance[label] = value
switch (label) {
case 'Cursor':
// 显示红色竖线
if (value) {
spectrumLineSeries.markLine.lineStyle.width = 2
} else {
spectrumLineSeries.markLine.lineStyle.width = 0
}
break
case 'Baseline':
2023-09-27 13:41:51 +08:00
this.redrawLineBySeriesName('BaseLine', this.energyData.baseLine, this.channelData.baseLine, value)
break
case 'Lc':
2023-09-27 13:41:51 +08:00
this.redrawLineBySeriesName('LcLine', this.energyData.lcLine, this.channelData.lcLine, value)
break
case 'SCAC':
2023-09-27 13:41:51 +08:00
this.redrawLineBySeriesName('ScacLine', this.energyData.scacLine, this.channelData.scacLine, value)
break
}
}
},
handleChangeNuclideVisible() {
this.nuclideLibraryVisible = !this.nuclideLibraryVisible
},
// 根据seriesName重绘线
redrawLineBySeriesName(seriesName, energyData, channelData, isShow = true, color) {
if (isShow) {
const data = this.isEnergy() ? energyData : channelData
2023-09-27 13:41:51 +08:00
this.setSeriesData(this.option.series, seriesName, this.transformPointListData(data.pointlist), color)
} else {
2023-09-27 13:41:51 +08:00
this.setSeriesData(this.option.series, seriesName, [])
}
},
// 重绘控制点
redrawCtrlPointBySeriesName() {
const series = findSeriesByName(this.option.series, 'BaseLine_Ctrl_Point')
2023-09-27 13:41:51 +08:00
const data = this.isEnergy() ? this.energyData.baseLineCP : this.channelData.baseLineCP
series.data = data.map(({ size, color, point: { x, y } }) => {
return {
value: [x, y],
itemStyle: {
color: 'transparent',
borderColor: color,
borderWidth: size / 2,
},
}
})
},
// 重绘Peak Line
redrawPeakLine() {
this.option.series = this.option.series.filter((item) => {
return !item.name.includes('Peak_')
})
2023-09-27 13:41:51 +08:00
const data = this.isEnergy() ? this.energyData.peakGroup : this.channelData.peakGroup
const peakLines = []
data.forEach((item, index) => {
peakLines.push(
2023-09-27 13:41:51 +08:00
buildLineSeries(`Peak_${index}`, this.transformPointListData(item.pointlist), item.color, {
zlevel: 6,
})
)
})
this.option.series.push(...peakLines)
},
// 重绘右上角的缩略图
redrawThumbnailChart() {
const series = findSeriesByName(this.thumbnailOption.series, 'Spectrum')
2023-09-27 13:41:51 +08:00
const data = this.isEnergy() ? this.energyData.spectrumLine : this.channelData.spectrumLine
series.data = this.transformPointListData(data.pointlist)
},
// 点击图表,设置红线
handleChartClick(param) {
const { offsetX, offsetY } = param
const point = getXAxisAndYAxisByPosition(this.getChart(), offsetX, offsetY)
if (point) {
const xAxis = point[0]
const spectrumLineSeries = findSeriesByName(this.option.series, 'Spectrum')
spectrumLineSeries.markLine.data[0].xAxis = xAxis
const channel = this.isEnergy() ? this.getChannelByEnergy(xAxis) : parseInt(xAxis.toFixed())
const energy = this.isEnergy()
? xAxis.toFixed(2)
2023-09-27 13:41:51 +08:00
: this.energyData.all.pointlist && this.energyData.all.pointlist[channel - 1].x.toFixed(2)
const counts = this.isEnergy()
? this.energyData.all.pointlist[channel - 1]
: this.channelData.all.pointlist[channel - 1]
this.option.title.text = `{a|Channel:${channel}} {a|Energy:${energy}} {a|Counts:${counts.y}} {a|Detectability:0}`
this.getSelPosNuclide(channel)
}
},
// 双击还原
handleChartDblClick() {
this.handleResetChart()
},
// 获取 Nuclide Library 数据
async getSelPosNuclide(channel) {
this.currChannel = channel
try {
this.isLoadingNuclide = true
const { sampleId, inputFileName: fileName } = this.sample
const { success, result, message } = await getAction('/gamma/getSelPosNuclide', {
sampleId,
channel,
fileName,
})
if (success) {
const { possible } = result
this.nuclideLibraryList = possible
} else {
this.$message.error(message)
}
} catch (error) {
this.list = []
console.error(error)
} finally {
this.isLoadingNuclide = false
}
},
// Nuclide Library 单项双击
handleNuclideDblClick(nuclide) {
this.nuclideLibraryVisible = false
this.nuclideReview.nuclide = nuclide
this.nuclideReview.visible = true
},
2023-06-28 19:25:11 +08:00
resize() {
this.$refs.chartRef.resize()
this.$refs.thumbnailChartRef.resize()
this.closePeakInfomationTooltip()
2023-06-28 19:25:11 +08:00
},
// peak info 点击左右方向
handlePeakInfoChange(direction) {
this.moveMarkLine(direction)
},
// 触发Peak Infomation
handleTogglePeak() {
const spectrumLineSeries = findSeriesByName(this.option.series, 'Spectrum')
const xAxis = spectrumLineSeries.markLine.data[0].xAxis
const channel = this.isEnergy() ? this.getChannelByEnergy(xAxis) : parseInt(xAxis.toFixed())
2023-09-27 13:41:51 +08:00
const index = this.channelData.peakGroup.findIndex((peakItem) => {
const allX = peakItem.pointlist.map((item) => item.x)
const max = Math.max(...allX)
const min = Math.min(...allX)
return channel >= min && channel <= max
})
if (-1 !== index) {
this.getPeakInfo(index)
} else {
this.closePeakInfomationTooltip()
}
},
// 获取 Peak 峰顶 信息
async getPeakInfo(index) {
try {
const { inputFileName: fileName } = this.sample
const { success, result, message } = await getAction('/gamma/clickPeakInformation', {
fileName,
index,
})
if (success) {
const html = result.replaceAll('\n', '<br>')
2023-09-27 13:41:51 +08:00
const currPeak = this.channelData.peakGroup[index]
const { x, y } = currPeak.pointlist.reduce((prev, curr) => {
return prev && prev.y > curr.y ? prev : curr
})
const [xPix, yPix] = this.getChart().convertToPixel({ seriesIndex: 0 }, [x, y])
this.peakInfomationTooltip.content = html
this.peakInfomationTooltip.visible = true
this.peakInfomationTooltip.left = xPix
this.peakInfomationTooltip.top = yPix - 20
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
}
},
// 关闭Peak Infomation
closePeakInfomationTooltip() {
this.peakInfomationTooltip.visible = false
},
2023-06-28 19:25:11 +08:00
/**
* 向某一个方向移动标记线
* @param { 'left'| 'right' } direction
*/
moveMarkLine(direction) {
const spectrumLineSeries = findSeriesByName(this.option.series, 'Spectrum')
const prevAxis = spectrumLineSeries.markLine.data[0].xAxis
2023-06-28 19:25:11 +08:00
// 获取每一段 Channel 中的最大值
2023-09-27 13:41:51 +08:00
const maxXAxises = this.channelData.peakGroup.map((item) => {
const allY = item.pointlist.map((item) => item.y)
const max = item.pointlist.find((point) => point.y == Math.max(...allY))
return max.x
})
let find = null
if (direction == 'right') {
// 找到第一个比prevAxis大的xAxis
find = maxXAxises.find((xAxis) => xAxis > prevAxis)
if (find) {
spectrumLineSeries.markLine.data[0].xAxis = find
}
} else if (direction == 'left') {
// 找到第一个比prevAxis小的xAxis
find = maxXAxises.reverse().find((xAxis) => xAxis < prevAxis)
if (find) {
spectrumLineSeries.markLine.data[0].xAxis = find
}
}
if (find) {
this.getSelPosNuclide(find)
}
},
// 鼠标按下时开启可刷选状态
handleMouseDown() {
this.getChart().dispatchAction({
type: 'takeGlobalCursor',
// 如果想变为“可刷选状态”,必须设置。不设置则会关闭“可刷选状态”。
key: 'brush',
brushOption: {
// 参见 brush 组件的 brushType。如果设置为 false 则关闭“可刷选状态”。
brushType: 'rect',
},
})
},
handleMouseUp() {
if (this.timer) {
window.clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
this.clearBrush()
}, 0)
},
clearBrush() {
const chart = this.getChart()
// 清理刷选的范围
chart.dispatchAction({
type: 'brush',
areas: [],
})
// 改为不可刷选状态
chart.dispatchAction({
type: 'takeGlobalCursor',
})
},
// 刷选完毕时
handleBrushEnd(param) {
this.closePeakInfomationTooltip()
const chart = this.$refs.chartRef.getChartInstance()
const areas = param.areas[0]
if (areas) {
const range = areas.range
const [[minX, maxX], [minY, maxY]] = range
const point1 = chart.convertFromPixel({ seriesIndex: 0 }, [minX, minY]).map((num) => parseInt(num.toFixed()))
const point2 = chart.convertFromPixel({ seriesIndex: 0 }, [maxX, maxY]).map((num) => parseInt(num.toFixed()))
// 拿到之前的最大值
const xAxisMax = getAxisMax(chart, 'xAxis')
const yAxisMax = getAxisMax(chart, 'yAxis')
// 拿到之前的最小值
const xAxisMin = this.option.xAxis.min
const yAxisMin = this.option.yAxis.min
let [x1, y2, x2, y1] = [...point1, ...point2] // 根据解析出的数据确定真实的范围
const xAxisLimit = rangeNumber(xAxisMin, xAxisMax)
const yAxisLimit = rangeNumber(yAxisMin, yAxisMax)
x1 = xAxisLimit(x1)
x2 = xAxisLimit(x2)
y1 = yAxisLimit(y1)
y2 = yAxisLimit(y2)
this.option.xAxis.min = x1
this.option.xAxis.max = x2
this.option.yAxis.min = y1
this.option.yAxis.max = y2
if (this.isEnergy()) {
const channel1 = this.getChannelByEnergy(x1)
const channel2 = this.getChannelByEnergy(x2)
this.setThumbnailChartRect(channel1, y2, channel2, y1)
} else {
this.setThumbnailChartRect(x1, y2, x2, y1)
}
const thumbnailChart = this.getThumbnailChart()
const [, maxYPixel] = thumbnailChart.convertToPixel({ seriesIndex: 0 }, [0, y1]) // 方框的上下两条边的yAxis转为pix
const [, minYPixel] = thumbnailChart.convertToPixel({ seriesIndex: 0 }, [0, y2])
const rectHeightPixel = maxYPixel - minYPixel // 计算方框的左右边长(pix)
this.halfHeightPixel = rectHeightPixel / 2
}
this.$nextTick(() => {
this.rangeScatter()
})
},
/**
* 因scatterGL 不受axis中max和min的控制手动处理溢出部分
* @param {Boolean} isReset 是否重置到初始状态
*/
rangeScatter(isReset) {
if (!this.isScatter()) {
return
}
const {
xAxis: { min: x1 },
yAxis: { min: y1 },
} = this.option
const chart = this.getChart()
const x2 = getAxisMax(chart, 'xAxis')
const y2 = getAxisMax(chart, 'yAxis')
const channelSpectrumData = {
2023-09-27 13:41:51 +08:00
...this.channelData.spectrumLine,
pointlist: isReset
2023-09-27 13:41:51 +08:00
? this.pointlistLimitY(this.channelData.spectrumLine.pointlist)
: this.pointlistLimit(this.channelData.spectrumLine.pointlist, x1, x2, y1, y2),
}
const energySpectrumData = {
2023-09-27 13:41:51 +08:00
...this.energyData.spectrumLine,
pointlist: isReset
2023-09-27 13:41:51 +08:00
? this.pointlistLimitY(this.energyData.spectrumLine.pointlist)
: this.pointlistLimit(this.energyData.spectrumLine.pointlist, x1, x2, y1, y2),
}
this.redrawLineBySeriesName('Spectrum', energySpectrumData, channelSpectrumData)
if (this.channelCompareLine) {
const channelCompareLine = {
...this.channelCompareLine,
pointlist: isReset
? this.pointlistLimitY(this.channelCompareLine.pointlist)
: this.pointlistLimit(this.channelCompareLine.pointlist, x1, x2, y1, y2),
}
const energyCompareLine = {
...this.energyCompareLine,
pointlist: isReset
? this.pointlistLimitY(this.energyCompareLine.pointlist)
: this.pointlistLimit(this.energyCompareLine.pointlist, x1, x2, y1, y2),
}
this.redrawLineBySeriesName('Compare', energyCompareLine, channelCompareLine)
}
},
/**
* 筛选范围内的点
* @param {*} pointlist
* @param {*} x1
* @param {*} x2
* @param {*} y1
* @param {*} y2
*/
pointlistLimit(pointlist, x1, x2, y1, y2) {
return pointlist.filter(({ x, y }) => x >= x1 && x <= x2 && y >= y1 && y <= y2)
},
pointlistLimitY(pointlist) {
return pointlist.filter(({ y }) => y >= 1)
},
// 在右上角缩略图中设置范围
setThumbnailChartRect(x1, y2, x2, y1) {
this.thumbnailChartRect = [x1, y2, x2, y1]
const thumbnailSpectrumLineSeries = findSeriesByName(this.thumbnailOption.series, 'Spectrum')
const { markLine } = thumbnailSpectrumLineSeries
const pointList = [
[
[x1, y1],
[x2, y1],
],
[
[x2, y1],
[x2, y2],
],
[
[x2, y2],
[x1, y2],
],
[
[x1, y2],
[x1, y1],
],
]
const lines = pointList.map((point) => {
return this.generateLineDataByTwoPoints(point[0], point[1])
})
markLine.data = lines
},
// 缩略图点击
handleThumbnailChartClick(param) {
const { offsetX, offsetY } = param
const thumbnailChart = this.getThumbnailChart()
const point = getXAxisAndYAxisByPosition(thumbnailChart, offsetX, offsetY)
if (point && this.thumbnailChartRect && this.thumbnailChartRect.length) {
const [x1, y2, x2, y1] = this.thumbnailChartRect
const halfWidth = Math.ceil((x2 - x1) / 2)
// 缩略图最大值转为pix
const [, maxYAxisPixel] = thumbnailChart.convertToPixel({ seriesIndex: 0 }, [
0,
getAxisMax(thumbnailChart, 'yAxis'),
])
const [, minYAxisPixel] = thumbnailChart.convertToPixel({ seriesIndex: 0 }, [0, 1])
let [xAxis, yAxis] = point
const xAxisMax = getAxisMax(thumbnailChart, 'xAxis')
const xAxisLimit = rangeNumber(1 + halfWidth, xAxisMax - halfWidth)
const halfHeightPixel = this.halfHeightPixel
const yAxisLimit = rangeNumber(maxYAxisPixel + halfHeightPixel, minYAxisPixel - halfHeightPixel)
xAxis = xAxisLimit(xAxis)
let [, yAxisPixel] = thumbnailChart.convertToPixel({ seriesIndex: 0 }, [0, yAxis])
yAxisPixel = yAxisLimit(yAxisPixel)
const minYAxis = thumbnailChart.convertFromPixel({ seriesIndex: 0 }, [0, yAxisPixel + halfHeightPixel])[1] // 再把y轴最小值从pix转为yAxis
const maxYAxis = thumbnailChart.convertFromPixel({ seriesIndex: 0 }, [0, yAxisPixel - halfHeightPixel])[1]
this.setThumbnailChartRect(xAxis - halfWidth, maxYAxis, xAxis + halfWidth, minYAxis)
if (this.isEnergy()) {
2023-09-27 13:41:51 +08:00
const x1 = parseInt(this.energyData.spectrumLine.pointlist[xAxis - halfWidth].x)
const x2 = parseInt(this.energyData.spectrumLine.pointlist[xAxis + halfWidth].x)
this.option.xAxis.min = x1
this.option.xAxis.max = x2
} else {
this.option.xAxis.min = xAxis - halfWidth
this.option.xAxis.max = xAxis + halfWidth
}
this.option.yAxis.min = minYAxis
this.option.yAxis.max = maxYAxis
this.$nextTick(() => {
this.rangeScatter()
})
}
},
2023-09-27 13:41:51 +08:00
/**
* 重置图表
*/
handleResetChart() {
this.option.xAxis.min = 1
this.option.xAxis.max = 'dataMax'
this.option.yAxis.min = 1
this.option.yAxis.max = 'dataMax'
const thumbnailSpectrumLineSeries = findSeriesByName(this.thumbnailOption.series, 'Spectrum')
thumbnailSpectrumLineSeries.markLine.data = []
this.thumbnailChartRect = []
2023-09-12 19:48:15 +08:00
this.closePeakInfomationTooltip()
this.$nextTick(() => {
this.rangeScatter(true)
})
},
// 从分析工具刷新部分数据
handleRefresh(data) {
this.handleResetState()
data.DetailedInformation = this.detailedInfomation
this.dataProsess(data)
},
// 分析工具Accept时刷新部分数据
handleAccept() {
console.log('%c [ 分析工具Accept时刷新部分数据 ]-1046', 'font-size:13px; background:pink; color:#bf2c9f;')
this.clearCompareLine()
},
// 显示比较弹窗
showCompareModal() {
if (this.isLoading) {
this.$message.warn('Sample is Loading')
return
}
this.handleResetChart()
this.clearCompareLine()
this.compareFileListModalVisible = true
},
// 文件之间对比
handleCompareWithFile([channelData, energyData]) {
this.channelCompareLine = channelData
this.energyCompareLine = energyData
this.redrawLineBySeriesName('Compare', energyData, channelData, true, channelData.color)
if (this.isScatter()) {
lineSeries.type = 'scatterGL'
}
this.$nextTick(() => {
this.thumbnailOption.yAxis.max = getAxisMax(this.getChart(), 'yAxis')
})
},
// 移除 Compare 线
clearCompareLine() {
const compareLine = findSeriesByName(this.option.series, 'Compare')
if (compareLine) {
compareLine.data = []
this.resetThumbnailChartDataMax()
}
this.channelCompareLine = undefined
this.energyCompareLine = undefined
},
// 重新分析
async reProcessing() {
if (this.isProcessing) {
return
}
if (this.isLoading) {
this.$message.warn('Sample is Loading')
return
}
try {
this.isLoading = true
this.handleResetState()
const { inputFileName: fileName } = this.sample
const { success, result, message } = await postAction(`/gamma/Reprocessing?fileName=${fileName}`)
if (success) {
result.DetailedInformation = this.detailedInfomation
this.dataProsess(result)
} 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)
}
// this.reprocessingModalVisible = true
},
2023-09-27 13:41:51 +08:00
/**
* 重置缩略图表y轴最大值
*/
resetThumbnailChartDataMax() {
this.thumbnailOption.yAxis.max = 'dataMax'
},
2023-09-27 13:41:51 +08:00
/**
* 重置图表配置
*/
resetChartOpts() {
this.opts.notMerge = false
this.option.brush = { toolbox: [] }
},
/**
* 根据两个点生成一个markLine直线
*/
generateLineDataByTwoPoints(point1, point2) {
return [
{
xAxis: point1[0],
yAxis: point1[1],
},
{
xAxis: point2[0],
yAxis: point2[1],
},
]
},
2023-09-27 13:41:51 +08:00
/**
* 根据energy获取channel
2023-09-27 14:53:17 +08:00
* @param {number} energy
2023-09-27 13:41:51 +08:00
*/
getChannelByEnergy(energy) {
let channel = 0
2023-09-27 13:41:51 +08:00
const pointlist = this.energyData.all.pointlist
for (let index = 1; index < pointlist.length; index++) {
const currEnergy = pointlist[index].x
if (currEnergy >= energy) {
2023-09-27 13:41:51 +08:00
const prevEnergy = pointlist[index - 1].x
if (currEnergy - energy > energy - prevEnergy.x) {
channel = index
} else {
channel = index + 1
}
break
}
}
return channel
},
2023-09-27 13:41:51 +08:00
/**
* 重置页面信息
*/
handleResetState() {
2023-09-27 13:41:51 +08:00
this.handleResetChart()
this.selectedChannel = -1
this.nuclideLibraryList = []
this.closePeakInfomationTooltip()
this.option.series = []
this.option.xAxis.name = 'Channel'
this.option.yAxis.type = 'value'
2023-09-27 14:53:17 +08:00
this.thumbnailOption.yAxis.type = 'value'
if (this.option.series.length) {
const spectrumLineSeries = findSeriesByName(this.option.series, 'Spectrum')
spectrumLineSeries.type = 'line'
spectrumLineSeries.symbol = 'none'
spectrumLineSeries.markLine.lineStyle.width = 2
}
2023-09-27 13:41:51 +08:00
const thumbnailSpectrumLineSeries = findSeriesByName(this.thumbnailOption.series, 'Spectrum')
thumbnailSpectrumLineSeries.type = 'line'
thumbnailSpectrumLineSeries.symbol = 'none'
this.graphAssistance = cloneDeep(graphAssistance)
},
2023-09-27 13:41:51 +08:00
/**
* 颜色改变
2023-09-27 14:53:17 +08:00
* @param {*} colorConfig
2023-09-27 13:41:51 +08:00
*/
handleColorChange(colorConfig) {
// 如果还没加载完,加载新的
if (this.isLoading) {
this.getSampleDetail()
}
// 否则修改已有颜色
else {
this.changeColor(colorConfig)
}
},
// 修改颜色
changeColor(colorConfig) {
const { Color_Spec, Color_Peak, Color_Lc, Color_Base, Color_Scac, Color_Compare, Color_Strip, Color_Fitbase } =
colorConfig
2023-09-27 13:41:51 +08:00
this.channelData.spectrumLine.color = Color_Spec
this.energyData.spectrumLine.color = Color_Spec
2023-09-27 13:41:51 +08:00
for (let i = 0; i < this.channelData.peakGroup.length; i++) {
this.channelData.peakGroup[i].color = Color_Peak
this.energyData.peakGroup[i].color = Color_Peak
}
2023-09-27 13:41:51 +08:00
this.channelData.lcLine.color = Color_Lc
this.energyData.lcLine.color = Color_Lc
2023-09-27 13:41:51 +08:00
this.channelData.baseLine.color = Color_Base
this.energyData.baseLine.color = Color_Base
2023-09-27 13:41:51 +08:00
this.channelData.scacLine.color = Color_Scac
this.energyData.scacLine.color = Color_Scac
if (this.channelCompareLine) {
this.channelCompareLine.color = Color_Compare
this.energyCompareLine.color = Color_Compare
}
this.changeColorBySeriesName('Spectrum', Color_Spec)
this.changePeakLineColor(Color_Peak)
this.changeColorBySeriesName('LcLine', Color_Lc)
this.changeColorBySeriesName('BaseLine', Color_Base)
this.changeColorBySeriesName('ScacLine', Color_Scac)
this.changeColorBySeriesName('Compare', Color_Compare)
const thumbnailChartSeries = findSeriesByName(this.thumbnailOption.series, 'Spectrum')
thumbnailChartSeries.itemStyle.color = Color_Spec
},
2023-09-27 13:41:51 +08:00
/**
* 根据series名修改颜色
2023-09-27 14:53:17 +08:00
* @param {*} seriesName
* @param {*} color
2023-09-27 13:41:51 +08:00
*/
changeColorBySeriesName(seriesName, color) {
const series = findSeriesByName(this.option.series, seriesName)
series.itemStyle.color = color
},
// 改变Peak的颜色
changePeakLineColor(color) {
this.option.series
.filter((item) => item.name.includes('Peak_'))
.forEach((item) => {
item.itemStyle.color = color
})
},
isEnergy() {
return this.graphAssistance.axisType == 'Energy'
},
isScatter() {
return this.graphAssistance.spectrumType == 'Scatter'
},
getChart() {
return this.$refs.chartRef.getChartInstance()
},
getThumbnailChart() {
return this.$refs.thumbnailChartRef.getChartInstance()
},
2023-09-27 13:41:51 +08:00
/**
* 设置图表数据和颜色
*/
setSeriesData(series, seriesName, data, color) {
const find = findSeriesByName(series, seriesName)
find.data = data
if (color) {
find.itemStyle.color = color
}
},
/**
* 转换pointlist类型数据到series的data可用的数据
*/
transformPointListData(pointlist) {
if (!pointlist) {
return []
}
return pointlist.map(({ x, y }) => [x, y])
},
/**
* 在返回的allData中查找指定的数据
* @param {Array} allData
* @param {*} name
* @param {*} group
*/
getLineData(allData, name, group, isList = false) {
const arrFunc = isList ? Array.prototype.filter : Array.prototype.find
return arrFunc.call(allData, (item) => item.name == name && item.group == group) || {}
},
2023-06-28 19:25:11 +08:00
},
watch: {
sample: {
2023-09-11 11:01:23 +08:00
handler(newVal, oldVal) {
console.log('newValnewVal', newVal)
2023-09-11 11:01:23 +08:00
if (newVal.sampleId) {
this.getSampleDetail()
} else {
this.getSampleDetail_file()
}
},
immediate: true,
},
},
2023-06-28 19:25:11 +08:00
}
</script>
<style lang="less" scoped>
.gamma-analysis {
height: 100%;
.ant-spin-nested-loading {
height: 100%;
::v-deep {
.ant-spin-container {
height: 100%;
}
}
}
&-main {
height: calc(100% - 51px);
display: flex;
overflow: auto hidden;
position: relative;
}
2023-06-28 19:25:11 +08:00
&-chart {
width: 100%;
2023-06-28 19:25:11 +08:00
height: 100%;
position: relative;
overflow: hidden;
2023-06-28 19:25:11 +08:00
}
&-thumbnail {
position: absolute;
top: 50px;
right: 10px;
width: 500px;
height: 20%;
background-color: #153e44;
2023-06-28 19:25:11 +08:00
}
}
</style>
<style lang="less">
.peak-infomation-tooltip {
position: absolute;
border-style: solid;
white-space: nowrap;
z-index: 9;
box-shadow: rgba(0, 0, 0, 0.2) 1px 2px 10px;
border-width: 1px;
border-radius: 4px;
padding: 10px;
border-color: rgb(255, 255, 255);
pointer-events: none;
background-color: #55a9fe;
border-color: #55a9fe;
}
</style>