Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e8d75b9877 | |||
| 8b78cdcdbd | |||
| f9bf41980b |
@@ -18,6 +18,9 @@ import 'echarts/lib/chart/line'
|
||||
import 'echarts/lib/component/dataZoom'
|
||||
import 'echarts/lib/component/tooltip'
|
||||
import 'echarts/lib/component/legend'
|
||||
import 'echarts/lib/component/legend/ScrollableLegendModel.js'
|
||||
import 'echarts/lib/component/legend/ScrollableLegendView.js'
|
||||
import 'echarts/lib/component/legend/scrollableLegendAction.js'
|
||||
import 'echarts/lib/component/axisPointer'
|
||||
import 'echarts/lib/component/grid'
|
||||
import 'echarts/lib/component/markArea'
|
||||
|
||||
@@ -256,7 +256,7 @@ export default {
|
||||
this.chartOverviewData.series[0].markArea.data[0][1].xAxis = this.startTime + ((this.endTime - this.startTime) * (this.dataZoomEnd / 100))
|
||||
this.zoomTime = 0
|
||||
},
|
||||
drawOverviewData: async function () {
|
||||
drawInitData: async function () {
|
||||
this.showChartLoading('overview')
|
||||
for (const meta in this.dataInfo) {
|
||||
let metaInfo
|
||||
@@ -467,7 +467,7 @@ export default {
|
||||
console.log(this.metaList)
|
||||
console.log(this.dataInfo)
|
||||
await this.register()
|
||||
await this.drawOverviewData()
|
||||
await this.drawInitData()
|
||||
this.dataZoomTimer = setInterval(this.checkDataZoom, 1000)
|
||||
this.$refs.top_control_panel.init()
|
||||
this.$refs.set_min_max.init()
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
<template>
|
||||
<div>
|
||||
<va-card>
|
||||
<p style="font-size: 125%; text-decoration: underline;"> Channel </p>
|
||||
<channels/>
|
||||
<p style="font-size: 125%; text-decoration: underline;"> Detect </p>
|
||||
<p :style="{color: this.$themes.primary}" class="display-6"> High pass filter </p>
|
||||
<cutoff-freq/>
|
||||
<filter-order/>
|
||||
<p :style="{color: this.$themes.danger}" class="display-6"> Threshold </p>
|
||||
<threshold/>
|
||||
<br/>
|
||||
<p class="display-6"> Waveform </p>
|
||||
<wave-length/>
|
||||
<prethreshold/>
|
||||
<refractory-period/>
|
||||
<detect-button @loadChartData="loadChartData"/>
|
||||
</va-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Channels from '@/components/analysis/spike/item/Channels.vue'
|
||||
import CutoffFreq from '@/components/analysis/spike/item/CutoffFreq.vue'
|
||||
import FilterOrder from '@/components/analysis/spike/item/FilterOrder.vue'
|
||||
import Prethreshold from '@/components/analysis/spike/item/Prethreshold.vue'
|
||||
import RefractoryPeriod from '@/components/analysis/spike/item/RefractoryPeriod.vue'
|
||||
import Threshold from '@/components/analysis/spike/item/Threshold.vue'
|
||||
import WaveLength from '@/components/analysis/spike/item/WaveLength.vue'
|
||||
import DetectButton from '@/components/analysis/spike/item/DetectButton.vue'
|
||||
|
||||
export default {
|
||||
name: 'control-panel',
|
||||
components: {
|
||||
Channels,
|
||||
CutoffFreq,
|
||||
FilterOrder,
|
||||
Prethreshold,
|
||||
RefractoryPeriod,
|
||||
Threshold,
|
||||
WaveLength,
|
||||
DetectButton,
|
||||
},
|
||||
props: {
|
||||
},
|
||||
async created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
},
|
||||
refreshChart (options) {
|
||||
this.$emit('refreshChart', options)
|
||||
},
|
||||
loadChartData () {
|
||||
this.$emit('loadChartData')
|
||||
},
|
||||
},
|
||||
// use watch because va-select with @change will have bug
|
||||
watch: {
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.flex-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex-child {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.flex-child1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.flex-child2 {
|
||||
flex: 0;
|
||||
}
|
||||
|
||||
.flex-child:first-child {
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
.right {
|
||||
float: right;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,354 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row row-equal">
|
||||
<div class="flex md12 xl3 xs12 sm12">
|
||||
<div class="row">
|
||||
<div class="flex sm12 xl12 md12 xs12">
|
||||
<va-accordion>
|
||||
<va-collapse class="mb-2" :isOpenDefault="true">
|
||||
<span slot="header">Control Panel</span>
|
||||
<div slot="body">
|
||||
<div>
|
||||
<control-panel :ref="'control_panel'" @loadChartData="drawSpikeData"/>
|
||||
</div>
|
||||
</div>
|
||||
</va-collapse>
|
||||
</va-accordion>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div :class="chartAreaClass">
|
||||
<div class="row" >
|
||||
<div class="flex sm12 xl12 md12 xs12">
|
||||
<spike-overview-chart :ref="'chart_overview'" :cardheight="'30vh'" :data="chartOverviewData"/>
|
||||
<spike-chart :ref="'chart_detail'" :cardheight="'60vh'" :data="chartDetailData"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters, mapMutations } from 'vuex'
|
||||
import SpikeOverviewChart from './SpikeOverviewChart.vue'
|
||||
import SpikeChart from './SpikeChart.vue'
|
||||
import ControlPanel from './ControlPanel.vue'
|
||||
import api from '@/data/api/index'
|
||||
import types from '@/store/modules/analysis/spike/types'
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
import newSeries from '@/factories/chart/seriesFactory'
|
||||
|
||||
export default {
|
||||
name: 'spike-data-replay',
|
||||
components: {
|
||||
SpikeOverviewChart,
|
||||
SpikeChart,
|
||||
ControlPanel,
|
||||
},
|
||||
computed: {
|
||||
...mapFields('spike', [
|
||||
'chartData',
|
||||
'chartOverviewData',
|
||||
'chartDetailData',
|
||||
'metaList',
|
||||
'selectedChannel',
|
||||
'cutoffFreq',
|
||||
'selectedThreshold',
|
||||
'upperThreshold',
|
||||
'lowerThreshold',
|
||||
'waveLength',
|
||||
'preThreshold',
|
||||
'refractoryPeriod',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
},
|
||||
async created () {
|
||||
this.chartOverviewData = await this.initChart({
|
||||
chartAllData: this.chartData,
|
||||
chartID: 0,
|
||||
gridLength: 1,
|
||||
type: 'overview',
|
||||
device: 'neulive',
|
||||
mode: 0,
|
||||
})
|
||||
this.chartDetailData = await this.initChart({
|
||||
chartAllData: this.chartData,
|
||||
chartID: 1,
|
||||
gridLength: 1,
|
||||
type: 'detail',
|
||||
device: 'neulive',
|
||||
mode: 0,
|
||||
})
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
dataInfo: {},
|
||||
maxTime: 0,
|
||||
chartAreaClass: ['flex', 'xs12', 'sm12', 'md12', 'xl9', 'pa-0'],
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
showChartLoading: function (chart) {
|
||||
const loadStyle = {
|
||||
text: '',
|
||||
color: '#cccccc',
|
||||
maskColor: 'rgba(255, 255, 255, 0.8)',
|
||||
zlevel: 0,
|
||||
}
|
||||
switch (chart) {
|
||||
case 'overview':
|
||||
this.$refs.chart_overview.showLoading(loadStyle)
|
||||
break
|
||||
case 'detail':
|
||||
this.$refs.chart_detail.showLoading(loadStyle)
|
||||
break
|
||||
default:
|
||||
this.$refs.chart_overview.showLoading(loadStyle)
|
||||
this.$refs.chart_detail.showLoading(loadStyle)
|
||||
break
|
||||
}
|
||||
},
|
||||
hideChartLoading: function (chart) {
|
||||
switch (chart) {
|
||||
case 'overview':
|
||||
this.$refs.chart_overview.hideLoading()
|
||||
break
|
||||
case 'detail':
|
||||
this.$refs.chart_detail.hideLoading()
|
||||
break
|
||||
default:
|
||||
this.$refs.chart_overview.hideLoading()
|
||||
this.$refs.chart_detail.hideLoading()
|
||||
break
|
||||
}
|
||||
},
|
||||
register: async function () {
|
||||
const gridLength = 1
|
||||
this.updateGridListChart({
|
||||
chartAllData: this.chartData,
|
||||
chartID: this.chartDetailData.chartID,
|
||||
gridLength: gridLength,
|
||||
})
|
||||
const register = this.metaList.map(meta => {
|
||||
this.registerChart({
|
||||
chartAllData: this.chartData,
|
||||
chartID: this.chartOverviewData.chartID,
|
||||
gridIndex: 0,
|
||||
deviceNameX: 'Time',
|
||||
deviceNameY: 'Neulive',
|
||||
deviceIDY: meta.name,
|
||||
channelY: this.selectedChannel,
|
||||
})
|
||||
this.registerChart({
|
||||
chartAllData: this.chartData,
|
||||
chartID: this.chartDetailData.chartID,
|
||||
gridIndex: 0,
|
||||
deviceNameX: 'Time',
|
||||
deviceNameY: 'Neulive',
|
||||
deviceIDY: meta.name,
|
||||
channelY: this.selectedChannel,
|
||||
})
|
||||
if (this.maxTime < parseInt(meta.time_duration)) {
|
||||
this.maxTime = parseInt(meta.time_duration)
|
||||
}
|
||||
})
|
||||
await Promise.all(register)
|
||||
|
||||
for (let i = 0; i < 2; i++) {
|
||||
// ID 0 = overview, ID 1 = detail
|
||||
this.updateAxisLabelChart({
|
||||
chartID: i,
|
||||
axis: 'x',
|
||||
axisIndex: 0,
|
||||
channel: this.selectedChannel,
|
||||
})
|
||||
this.updateAxisLabelChart({
|
||||
chartID: i,
|
||||
axis: 'y',
|
||||
axisIndex: 0,
|
||||
channel: this.selectedChannel,
|
||||
})
|
||||
this.updateDataZoomChart({
|
||||
chartAllData: this.chartData,
|
||||
chartID: i,
|
||||
})
|
||||
}
|
||||
|
||||
this.updateChartSamplingChart({ chartID: this.chartOverviewData.chartID, seriesIndex: 0, method: function (frame) { return frame[0] } })
|
||||
this.chartOverviewData.xAxis[0].min = 0
|
||||
this.chartOverviewData.xAxis[0].max = this.maxTime
|
||||
},
|
||||
drawSpikeData: async function () {
|
||||
this.showChartLoading('overview')
|
||||
this.showChartLoading('detail')
|
||||
for (const meta in this.dataInfo) {
|
||||
let metaInfo
|
||||
this.metaList.forEach(_meta => {
|
||||
if (parseInt(_meta.id) === parseInt(meta)) {
|
||||
metaInfo = _meta
|
||||
}
|
||||
})
|
||||
const sampleRate = (800000 / metaInfo.parameter_set.ADC_CLOCK) / JSON.parse(metaInfo.channels).length // Hz
|
||||
const period = 1e6 / sampleRate
|
||||
|
||||
let thresholdValue
|
||||
if (this.selectedThreshold === 'over') {
|
||||
thresholdValue = this.upperThreshold
|
||||
} else if (this.selectedThreshold === 'bellow') {
|
||||
thresholdValue = this.lowerThreshold
|
||||
}
|
||||
|
||||
const randomColorArray = []
|
||||
|
||||
// [Region] whole processed signal
|
||||
const allSpikeData = await api.analysis.spikeDetect({
|
||||
id: meta,
|
||||
channel: this.selectedChannel,
|
||||
cut_off_freq: this.cutoffFreq,
|
||||
threshold: [
|
||||
`'${this.selectedThreshold}'`,
|
||||
thresholdValue,
|
||||
],
|
||||
waveForm: [this.waveLength, this.preThreshold, this.refractoryPeriod],
|
||||
ret_data_type: 'all',
|
||||
})
|
||||
|
||||
this.chartOverviewData.series[0].data.length = 0
|
||||
this.chartOverviewData.color = ['#000000'] // black
|
||||
const splitData = allSpikeData.data.split('\n')
|
||||
const allTimeArray = splitData[0].split(' ')
|
||||
const allTimeArrayLength = allTimeArray.length
|
||||
const allSignalArray = splitData[1].split(' ')
|
||||
const allTimeMarkIndexArray = splitData[2].split(' ')
|
||||
for (let i = 0; i < allTimeArrayLength; i++) {
|
||||
this.chartOverviewData.series[0].data.push([parseInt(allTimeArray[i]), allSignalArray[i]])
|
||||
}
|
||||
this.chartOverviewData.xAxis[0].min = parseInt(allTimeArray[0])
|
||||
this.chartOverviewData.xAxis[0].max = parseInt(allTimeArray[allTimeArrayLength - 1])
|
||||
this.chartOverviewData.xAxis[0].axisLabel.show = true
|
||||
|
||||
this.chartOverviewData.series[0].markArea.data.length = 0
|
||||
for (let i = 0; i < allTimeMarkIndexArray.length; i++) {
|
||||
// generate color array for overview markArea and detail chart series
|
||||
const randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16) // ref: https://css-tricks.com/snippets/javascript/random-hex-color/
|
||||
randomColorArray.push(randomColor)
|
||||
if (Number.isInteger(parseInt(allTimeMarkIndexArray[i]))) { // cuz maybe is '' if no any match after filtering
|
||||
const timeMarkIndex = parseInt(allTimeMarkIndexArray[i])
|
||||
const start = parseInt(this.chartOverviewData.series[0].data[timeMarkIndex - parseInt(this.preThreshold / period)][0])
|
||||
const end = parseInt(this.chartOverviewData.series[0].data[timeMarkIndex + parseInt(this.refractoryPeriod / period)][0])
|
||||
this.chartOverviewData.series[0].markArea.data.push([
|
||||
{
|
||||
itemStyle: {
|
||||
color: randomColor,
|
||||
},
|
||||
name: String(i + 1),
|
||||
xAxis: start,
|
||||
},
|
||||
{
|
||||
xAxis: end,
|
||||
},
|
||||
])
|
||||
}
|
||||
}
|
||||
// [EndRegion]
|
||||
|
||||
// [Region] each detailed signal piece
|
||||
const spikeData = await api.analysis.spikeDetect({
|
||||
id: meta,
|
||||
channel: this.selectedChannel,
|
||||
cut_off_freq: this.cutoffFreq,
|
||||
threshold: [
|
||||
`'${this.selectedThreshold}'`,
|
||||
thresholdValue,
|
||||
],
|
||||
waveForm: [this.waveLength, this.preThreshold, this.refractoryPeriod],
|
||||
ret_data_type: 'partial',
|
||||
})
|
||||
|
||||
for (let i = 0; i < this.chartDetailData.series.length; i++) {
|
||||
this.chartDetailData.series[i].name = ''
|
||||
this.chartDetailData.series[i].data.length = 0
|
||||
}
|
||||
const detailSignalArray = Object.values(spikeData.data)
|
||||
if (detailSignalArray.length <= 8) {
|
||||
this.chartDetailData.tooltip.show = true
|
||||
} else {
|
||||
this.chartDetailData.tooltip.show = false
|
||||
}
|
||||
this.chartDetailData.legend.data.length = 0
|
||||
this.chartDetailData.legend.type = 'scroll'
|
||||
this.chartDetailData.legend.top = '0.25%'
|
||||
// this.chartDetailData.legendpageButtonPosition = 'start'
|
||||
this.chartDetailData.animation = false
|
||||
this.chartDetailData.color = []
|
||||
for (let i = 0; i < detailSignalArray.length; i++) {
|
||||
const detailSignal = detailSignalArray[i].split(' ')
|
||||
const arrayLength = detailSignal.length
|
||||
const step = parseInt(this.waveLength) / (arrayLength - 1)
|
||||
const xAxisIndex = 0
|
||||
const yAxisIndex = 0
|
||||
const legendName = 'T_' + String(i + 1)
|
||||
if (this.chartDetailData.series.length <= i) {
|
||||
const _series = newSeries('line', legendName, xAxisIndex, yAxisIndex, [-1, -1], [metaInfo.name, this.selectedChannel], null, null)
|
||||
this.chartDetailData.series.push(_series)
|
||||
}
|
||||
for (let j = 0; j < arrayLength; j++) {
|
||||
this.chartDetailData.series[i].data.push([j * step, detailSignal[j]])
|
||||
}
|
||||
// push legendName
|
||||
this.chartDetailData.legend.data.push(legendName)
|
||||
this.chartDetailData.series[i].name = legendName
|
||||
// set legend and series color
|
||||
this.chartDetailData.color.push(randomColorArray[i])
|
||||
}
|
||||
this.chartDetailData.xAxis[0].min = 0
|
||||
this.chartDetailData.xAxis[0].max = parseInt(this.waveLength)
|
||||
this.chartDetailData.xAxis[0].axisLabel.show = true
|
||||
// [EndRegion]
|
||||
}
|
||||
this.hideChartLoading()
|
||||
console.log(this.chartOverviewData)
|
||||
console.log(this.chartDetailData)
|
||||
},
|
||||
...mapActions('spike', [types.chart.init, types.chart.initSelectedChannel, types.chart.register, types.chart.clear, types.chart.updateGridList, types.chart.updateDataZoom]),
|
||||
...mapActions('spike', [types.meta.init]),
|
||||
...mapActions('spike', [types.rec.init, types.rec.intoData, types.rec.initDisplaySetting, types.rec.updateDisplaySetting]),
|
||||
|
||||
...mapMutations('spike', [types.chart.updateAxisLabel, types.chart.updateChartSampling]),
|
||||
...mapMutations('spike', [types.meta.updateByIndex]),
|
||||
|
||||
...mapGetters('spike', [types.meta.getAll]),
|
||||
...mapGetters('spike', [types.rec.getAll]),
|
||||
},
|
||||
// use watch because va-select with @change will have bug
|
||||
watch: {
|
||||
},
|
||||
async mounted () {
|
||||
const metaIDList = this.$route.params.metaList.split('-')
|
||||
await this.initMeta({ metaIDList: metaIDList, api: api })
|
||||
this.metaList = this.getAllMeta()
|
||||
this.initSelectedChannelChart({ metaIndex: 0 })
|
||||
await this.initRec({ api: api })
|
||||
this.dataInfo = this.getAllRec()
|
||||
console.log(this.metaList)
|
||||
console.log(this.dataInfo)
|
||||
await this.register()
|
||||
this.$refs.control_panel.init()
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$refs.chart_detail.clear()
|
||||
for (const id in this.chartData) {
|
||||
for (const _series of this.chartData[id].series) {
|
||||
_series.length = 0
|
||||
}
|
||||
delete this.chartData[id]
|
||||
}
|
||||
this.clearChart({ chartAllData: this.chartData })
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div class="flex" :class="cardclass">
|
||||
<va-card :style="'height: ' + cardheight + ';'">
|
||||
<chart :ref="'chart_ref'" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" :options="data" @dataZoom="updateZoom" :auto-resize="true"></chart>
|
||||
</va-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import types from '@/store/modules/analysis/spike/types'
|
||||
// import { chartData } from '../../../../data/task/ChartsManagement'
|
||||
|
||||
export default {
|
||||
name: 'spike-replay-chart',
|
||||
components: {
|
||||
},
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
cardclass: {
|
||||
type: Array,
|
||||
default: function () {
|
||||
return ['xs12', 'md12', 'xl12', 'sm12']
|
||||
},
|
||||
},
|
||||
cardheight: {
|
||||
type: String,
|
||||
default: '82vh',
|
||||
},
|
||||
cardwidth: {
|
||||
type: String,
|
||||
default: 'auto',
|
||||
},
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
methods: {
|
||||
resize: function () {
|
||||
if (this.$refs.chart_ref != null) {
|
||||
this.$refs.chart_ref.resize()
|
||||
}
|
||||
},
|
||||
updateZoom: function (e) {
|
||||
this.$emit('dataZoomEvent', e)
|
||||
},
|
||||
mergeOptions (options) {
|
||||
this.$refs.chart_ref.mergeOptions(options)
|
||||
},
|
||||
turnOnAxisEventHandler (eventName, query, handler, attr) {
|
||||
const chartID = 1
|
||||
this.updateAxisEventHandlerChart({
|
||||
chartID: chartID,
|
||||
axis: attr.axis,
|
||||
status: 'on',
|
||||
})
|
||||
// doc: https://echarts.apache.org/zh/api.html#echartsInstance.on
|
||||
this.$refs.chart_ref.chart._zr.on(eventName, query, handler)
|
||||
},
|
||||
turnOffAxisEventHandler (eventName, handler, attr) {
|
||||
const chartID = 1
|
||||
this.updateAxisEventHandlerChart({
|
||||
chartID: chartID,
|
||||
axis: attr.axis,
|
||||
status: 'off',
|
||||
})
|
||||
// doc: https://echarts.apache.org/zh/api.html#echartsInstance.off
|
||||
this.$refs.chart_ref.chart._zr.off(eventName, handler)
|
||||
},
|
||||
showLoading (options) {
|
||||
this.$refs.chart_ref.showLoading(options)
|
||||
},
|
||||
hideLoading () {
|
||||
this.$refs.chart_ref.hideLoading()
|
||||
},
|
||||
clear () {
|
||||
this.$refs.chart_ref.clear()
|
||||
},
|
||||
|
||||
...mapMutations('spike', [types.chart.updateAxisEventHandler]),
|
||||
},
|
||||
async mounted () {
|
||||
this.resizeTimer = setInterval(this.resize, 1000)
|
||||
},
|
||||
destroyed () {
|
||||
clearInterval(this.resizeTimer)
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss'>
|
||||
.va-card {
|
||||
&__body {
|
||||
padding-top: 0.25rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div class="flex" :class="cardclass">
|
||||
<va-card :style="'height: ' + cardheight + ';'">
|
||||
<chart :ref="'chart_ref'" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" :options="data" @dataZoom="updateZoom" :auto-resize="true"></chart>
|
||||
</va-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import { chartData } from '../../../../data/task/ChartsManagement'
|
||||
|
||||
export default {
|
||||
name: 'spike-overview-chart',
|
||||
components: {
|
||||
},
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
cardclass: {
|
||||
type: Array,
|
||||
default: function () {
|
||||
return ['xs12', 'md12', 'xl12', 'sm12']
|
||||
},
|
||||
},
|
||||
cardheight: {
|
||||
type: String,
|
||||
default: '82vh',
|
||||
},
|
||||
cardwidth: {
|
||||
type: String,
|
||||
default: 'auto',
|
||||
},
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
methods: {
|
||||
resize: function () {
|
||||
if (this.$refs.chart_ref != null) {
|
||||
this.$refs.chart_ref.resize()
|
||||
}
|
||||
},
|
||||
mergeOptions (options) {
|
||||
this.$refs.chart_ref.mergeOptions(options)
|
||||
},
|
||||
updateZoom: function (e) {
|
||||
this.$emit('dataZoomEvent', e)
|
||||
},
|
||||
showLoading (options) {
|
||||
this.$refs.chart_ref.showLoading(options)
|
||||
},
|
||||
hideLoading () {
|
||||
this.$refs.chart_ref.hideLoading()
|
||||
},
|
||||
clear () {
|
||||
this.$refs.chart_ref.clear()
|
||||
},
|
||||
},
|
||||
async mounted () {
|
||||
this.resizeTimer = setInterval(this.resize, 1000)
|
||||
},
|
||||
destroyed () {
|
||||
clearInterval(this.resizeTimer)
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss'>
|
||||
.va-card {
|
||||
&__body {
|
||||
padding-top: 0.25rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div>
|
||||
<va-button-toggle small flat v-model="selectedChannel" :options="selectedChannelOptions" @click.native="reloadData(selectedChannel)"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
name: 'Channels',
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
...mapFields('spike', [
|
||||
'selectedChannel',
|
||||
'selectedChannelOptions',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
reloadData (val) {
|
||||
this.selectedChannel = val
|
||||
},
|
||||
},
|
||||
async mounted () {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<div class="row flex sm12 xl12 md12 xs12 align--center my-0 py-0">
|
||||
<div class="flex sm6 xl6 md6 xs6 px-0 mx-0">
|
||||
<p>Cut-off Freq<p/>
|
||||
</div>
|
||||
<div class="flex sm6 xl6 md6 xs6 px-0 mx-0">
|
||||
<va-input
|
||||
@mouseleave.native="itemChange(cutoffFreq)"
|
||||
@keyup.enter="itemChange(cutoffFreq)"
|
||||
@blur="itemChange(cutoffFreq)"
|
||||
v-model="cutoffFreq"
|
||||
class="mb-0"
|
||||
>
|
||||
<p slot="append" style="margin-right: 0;" small>
|
||||
Hz
|
||||
</p>
|
||||
</va-input>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
name: 'CutoffFreq',
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
...mapFields('spike', [
|
||||
'cutoffFreq',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
itemChange (val) {
|
||||
this.cutoffFreq = val
|
||||
},
|
||||
},
|
||||
async mounted () {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div>
|
||||
<va-button class="right" small @click="startDetect">
|
||||
Start Detect
|
||||
</va-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import types from '@/store/modules/analysis/spike/types'
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
import { mapMutations } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Channels',
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
...mapFields('spike', [
|
||||
'chartDetailData',
|
||||
'selectedChannel',
|
||||
'waveLength',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
startDetect () {
|
||||
this.$emit('loadChartData')
|
||||
},
|
||||
...mapMutations('spike', [types.chart.updateAxisLabel]),
|
||||
},
|
||||
async mounted () {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<div class="row flex sm12 xl12 md12 xs12 align--center my-0 py-0">
|
||||
<div class="flex sm6 xl6 md6 xs6 px-0 mx-0">
|
||||
<p>Filter order<p/>
|
||||
</div>
|
||||
<div class="flex sm6 xl6 md6 xs6 px-0 mx-0">
|
||||
<va-input
|
||||
@mouseleave.native="itemChange(filterOrder)"
|
||||
@keyup.enter="itemChange(filterOrder)"
|
||||
@blur="itemChange(filterOrder)"
|
||||
v-model="filterOrder"
|
||||
class="mb-0"
|
||||
>
|
||||
</va-input>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
name: 'FilterOrder',
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
...mapFields('spike', [
|
||||
'filterOrder',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
itemChange (val) {
|
||||
this.filterOrder = val
|
||||
},
|
||||
},
|
||||
async mounted () {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<div class="row flex sm12 xl12 md12 xs12 align--center my-0 py-0">
|
||||
<div class="flex sm6 xl6 md6 xs6 px-0 mx-0">
|
||||
<p>Prethreshold<p/>
|
||||
</div>
|
||||
<div class="flex sm6 xl6 md6 xs6 px-0 mx-0">
|
||||
<va-input
|
||||
@mouseleave.native="itemChange(preThreshold)"
|
||||
@keyup.enter="itemChange(preThreshold)"
|
||||
@blur="itemChange(preThreshold)"
|
||||
v-model="preThreshold"
|
||||
class="mb-0"
|
||||
>
|
||||
<p slot="append" style="margin-right: 0;" small>
|
||||
µs
|
||||
</p>
|
||||
</va-input>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
name: 'Prethreshold',
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
...mapFields('spike', [
|
||||
'preThreshold',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
itemChange (val) {
|
||||
this.preThreshold = val
|
||||
},
|
||||
},
|
||||
async mounted () {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<div class="row flex sm12 xl12 md12 xs12 align--center my-0 py-0">
|
||||
<div class="flex sm7 xl7 md7 xs7 px-0 mx-0">
|
||||
<p>Refractory period<p/>
|
||||
</div>
|
||||
<div class="flex sm5 xl5 md5 xs5 px-0 mx-0">
|
||||
<va-input
|
||||
@mouseleave.native="itemChange(refractoryPeriod)"
|
||||
@keyup.enter="itemChange(refractoryPeriod)"
|
||||
@blur="itemChange(refractoryPeriod)"
|
||||
v-model="refractoryPeriod"
|
||||
class="mb-0"
|
||||
>
|
||||
<p slot="append" style="margin-right: 0;" small>
|
||||
µs
|
||||
</p>
|
||||
</va-input>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
name: 'RefractoryPeriod',
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
...mapFields('spike', [
|
||||
'refractoryPeriod',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
itemChange (val) {
|
||||
this.refractoryPeriod = val
|
||||
},
|
||||
},
|
||||
async mounted () {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div class="row flex sm12 xl12 md12 xs12 align--center my-0 py-0">
|
||||
<va-radio-button
|
||||
v-for="(option, index) in options"
|
||||
:key="index"
|
||||
v-model="selectedThreshold"
|
||||
:option="option"
|
||||
:label="`${option}`"
|
||||
/>
|
||||
<va-input
|
||||
v-if="selectedThreshold === 'over'"
|
||||
@mouseleave.native="itemChange(upperThreshold, 'upper')"
|
||||
@keyup.enter="itemChange(upperThreshold, 'upper')"
|
||||
@blur="itemChange(upperThreshold, 'upper')"
|
||||
v-model="upperThreshold"
|
||||
class="mb-0"
|
||||
>
|
||||
<p slot="append" style="margin-right: 0;" small>
|
||||
µV
|
||||
</p>
|
||||
</va-input>
|
||||
<va-input
|
||||
v-if="selectedThreshold === 'bellow'"
|
||||
@mouseleave.native="itemChange(lowerThreshold, 'lower')"
|
||||
@keyup.enter="itemChange(lowerThreshold, 'lower')"
|
||||
@blur="itemChange(lowerThreshold, 'lower')"
|
||||
v-model="lowerThreshold"
|
||||
class="mb-0"
|
||||
>
|
||||
<p slot="append" style="margin-right: 0;" small>
|
||||
µV
|
||||
</p>
|
||||
</va-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
name: 'Threshold',
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
...mapFields('spike', [
|
||||
'selectedThreshold',
|
||||
'upperThreshold',
|
||||
'lowerThreshold',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
options: [
|
||||
// 'Auto',
|
||||
'over',
|
||||
'bellow',
|
||||
],
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
itemChange (val, type) {
|
||||
if (type === 'upper') {
|
||||
this.upperThreshold = val
|
||||
} else if (type === 'lower') {
|
||||
this.lowerThreshold = val
|
||||
}
|
||||
},
|
||||
},
|
||||
async mounted () {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<div class="row flex sm12 xl12 md12 xs12 align--center my-0 py-0">
|
||||
<div class="flex sm7 xl7 md7 xs7 px-0 mx-0">
|
||||
<p>Waveform length<p/>
|
||||
</div>
|
||||
<div class="flex sm5 xl5 md5 xs5 px-0 mx-0">
|
||||
<va-input
|
||||
@mouseleave.native="itemChange(waveLength)"
|
||||
@keyup.enter="itemChange(waveLength)"
|
||||
@blur="itemChange(waveLength)"
|
||||
v-model="waveLength"
|
||||
class="mb-0"
|
||||
>
|
||||
<p slot="append" style="margin-right: 0;" small>
|
||||
µs
|
||||
</p>
|
||||
</va-input>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
name: 'WaveLength',
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
...mapFields('spike', [
|
||||
'waveLength',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
itemChange (val) {
|
||||
this.waveLength = val
|
||||
},
|
||||
},
|
||||
async mounted () {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<span> Resample: {{ currentScale }} to 1 </span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
name: 'show-resample-rate',
|
||||
components: {
|
||||
},
|
||||
props: {
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapFields('spike', [
|
||||
'currentScale',
|
||||
]),
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -182,6 +182,9 @@
|
||||
<va-popover :message="`replay ${props.rowData.name}`" placement="top">
|
||||
<va-button flat small color="gray" icon="fa fa-eye" v-if="props.rowData.type !== 'folder'" @click.stop="replay(props.rowData)"/>
|
||||
</va-popover>
|
||||
<va-popover :message="`spike ${props.rowData.name}`" placement="top">
|
||||
<va-button flat small color="gray" icon="fa fa-filter" v-if="props.rowData.type !== 'folder'" @click.stop="spike(props.rowData)"/>
|
||||
</va-popover>
|
||||
<va-popover :message="`edit ${props.rowData.name}`" placement="top">
|
||||
<va-button flat small color="gray" icon="fa fa-pencil" @click.stop="editFileConfirm(props.rowData)"/>
|
||||
</va-popover>
|
||||
@@ -668,6 +671,11 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
spike: function (meta) {
|
||||
this.$router.push({
|
||||
path: '/admin/data-spike/' + meta.id,
|
||||
})
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
function getTime (val) {
|
||||
const hour = parseInt(val / 3.6e9)
|
||||
const minute = parseInt((val % 3.6e9) / 1000000 / 60)
|
||||
const second = parseInt((val % 6e7) / 1000000)
|
||||
const millisecond = parseInt((val % 1e6) / 1000)
|
||||
let label = ''
|
||||
const hour = Math.floor(val / 3.6e9)
|
||||
const minute = Math.floor((val % 3.6e9) / 1000000 / 60)
|
||||
const second = Math.floor((val % 6e7) / 1000000)
|
||||
const millisecond = Math.floor((val % 1e6) / 1000)
|
||||
const microsecond = Math.floor(val % 1e6) - 1000 * millisecond
|
||||
if (hour > 0) {
|
||||
label += hour + ' h '
|
||||
}
|
||||
@@ -16,7 +17,9 @@ function getTime (val) {
|
||||
if (millisecond > 0) {
|
||||
label += millisecond + ' ms '
|
||||
}
|
||||
// const label = parseInt(parseInt(val / 1000000) / 60) + ' m ' + parseInt((val % 60000000) / 1000000) + ' s'
|
||||
if (microsecond > 0 && hour === 0 && minute === 0 && second === 0) {
|
||||
label += microsecond + ' µs '
|
||||
}
|
||||
return label
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +107,11 @@ export default new Router({
|
||||
path: 'data-replay/elite/:metaList?',
|
||||
component: () => import('../components/analysis/replay/elite/EliteDataReplay.vue'),
|
||||
},
|
||||
{
|
||||
name: 'data-spike',
|
||||
path: 'data-spike/:metaList?',
|
||||
component: () => import('../components/analysis/spike/Spike.vue'),
|
||||
},
|
||||
{
|
||||
name: 'task-content',
|
||||
path: 'task-content/:taskID?',
|
||||
|
||||
@@ -9,6 +9,7 @@ import state from './state'
|
||||
import mutations from './mutations'
|
||||
|
||||
import replay from './modules/analysis/replay'
|
||||
import spike from './modules/analysis/spike'
|
||||
import file from './modules/file'
|
||||
import download from './modules/download'
|
||||
|
||||
@@ -22,6 +23,7 @@ const store = new Vuex.Store({
|
||||
modules: {
|
||||
taskContent,
|
||||
replay,
|
||||
spike,
|
||||
setting,
|
||||
download,
|
||||
file,
|
||||
|
||||
@@ -261,62 +261,6 @@ const actions = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* set time format to xAxis by chart ID
|
||||
*
|
||||
* @param {object} chartAllData
|
||||
* @param {int} chartID
|
||||
* @param {int} xAxisIndex
|
||||
* @param {object} series : chart series (echarts series)
|
||||
*/
|
||||
[typePath.setTimeXAxis]: (state, payload) => {
|
||||
payload.chartAllData[payload.chartID].xAxis[payload.xAxisIndex].axisLabel.formatter = function (val) {
|
||||
const label = parseInt(parseInt(val / 1000000) / 60) + ' m ' + parseInt((val % 60000000) / 1000000) + ' s'
|
||||
return label
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* set value format by chart ID
|
||||
*
|
||||
* @param {object} chartAllData
|
||||
* @param {int} chartID
|
||||
* @param {string} axis ('x' or 'y')
|
||||
* @param {int} axisIndex
|
||||
* @param {optional, object} format
|
||||
*/
|
||||
[typePath.setAxisValueFormat]: (state, payload) => {
|
||||
let name = '' // string
|
||||
let unit = '' // string
|
||||
let unitScale = 1 // int
|
||||
if (payload.format !== undefined) {
|
||||
name = payload.format.name // string
|
||||
unit = payload.format.unit // string
|
||||
unitScale = payload.format.unitScale // int
|
||||
}
|
||||
if (payload.axis === 'x') {
|
||||
payload.chartAllData[payload.chartID].xAxis[payload.axisIndex].axisLabel.formatter = function (val) {
|
||||
if (name !== 'time') {
|
||||
const label = (val / unitScale).toFixed(2) + unit
|
||||
return label
|
||||
} else {
|
||||
var hr = Math.floor(val / 3600000000)
|
||||
var min = Math.floor((val - (hr * 3600000000)) / 60000000)
|
||||
var sec = parseInt((val - (hr * 3600000000) - (min * 60000000)) / 1000000)
|
||||
while (min.length < 2) { min = '0' + min }
|
||||
while (sec.length < 2) { sec = '0' + min }
|
||||
if (hr) hr += 'h'
|
||||
return hr + min + 'm' + sec + 's'
|
||||
}
|
||||
}
|
||||
} else if (payload.axis === 'y') {
|
||||
payload.chartAllData[payload.chartID].yAxis[payload.axisIndex].axisLabel.formatter = function (val) {
|
||||
const label = (val / unitScale).toFixed(2) + unit
|
||||
return label
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* register device-channel to chartData
|
||||
*
|
||||
@@ -472,19 +416,6 @@ const actions = {
|
||||
return chartData
|
||||
},
|
||||
|
||||
/**
|
||||
* reset chart axis label
|
||||
*
|
||||
* @param {object} chartData
|
||||
*/
|
||||
[typePath.resetChartDataAxisLabel]: async (state, payload) => {
|
||||
const axisArray = payload.chartData.yAxis
|
||||
for (let index = 0; index < axisArray.length; ++index) {
|
||||
payload.chartData.yAxis[index].max = null
|
||||
payload.chartData.yAxis[index].min = null
|
||||
}
|
||||
},
|
||||
|
||||
// /**
|
||||
// * remove device-channel from chart TODO
|
||||
// *
|
||||
|
||||
@@ -20,8 +20,6 @@ const types = {
|
||||
pushSeries: 'pushSeriesChart',
|
||||
pushAxis: 'pushAxisChart',
|
||||
pushLegendName: 'pushLegendNameChart',
|
||||
setTimeXAxis: 'setTimeXAxisChart',
|
||||
setAxisValueFormat: 'setAxisValueFormatChart',
|
||||
pushGridSeries: 'pushGridSeriesChart',
|
||||
deleteByID: 'deleteByIDChart',
|
||||
update: 'updateChart',
|
||||
@@ -34,8 +32,6 @@ const types = {
|
||||
updateRegistered: 'updateRegisteredChart',
|
||||
updateAxisSplitNumber: 'updateAxisSplitNumberChart',
|
||||
updateChartSampling: 'updateChartSamplingChart',
|
||||
|
||||
resetChartDataAxisLabel: 'resetChartDataAxisLabelChart',
|
||||
},
|
||||
meta: {
|
||||
init: 'initMeta',
|
||||
|
||||
@@ -0,0 +1,506 @@
|
||||
import newSeries from '@/factories/chart/seriesFactory'
|
||||
import newChart from '@/factories/chart/chartFactory'
|
||||
import newTooltip from '@/factories/chart/tooltipFactory'
|
||||
import newDataZoom from '@/factories/chart/dataZoomFactory'
|
||||
import types from '@/store/modules/analysis/spike/types'
|
||||
|
||||
const typePath = types.chart
|
||||
|
||||
// generate x axis format
|
||||
function makeXAxis (gridIndex, type) {
|
||||
const xAxis = {
|
||||
type: type,
|
||||
gridIndex: gridIndex,
|
||||
axisLine: { show: false, onZero: false, lineStyle: { color: '#aaa' } },
|
||||
axisTick: { show: false },
|
||||
axisLabel: {
|
||||
show: false,
|
||||
showMinLabel: true,
|
||||
showMaxLabel: true,
|
||||
color: '#aaa',
|
||||
},
|
||||
splitLine: { show: true, lineStyle: { color: '#eee' } },
|
||||
splitNumber: 5,
|
||||
scale: true,
|
||||
min: null,
|
||||
max: null,
|
||||
}
|
||||
return xAxis
|
||||
}
|
||||
|
||||
// generate y axis format
|
||||
function makeYAxis (gridIndex, type) {
|
||||
return {
|
||||
type: type,
|
||||
gridIndex: gridIndex,
|
||||
axisTick: { show: false },
|
||||
axisLine: { show: false }, // color: '#ccc' } },
|
||||
axisLabel: { show: true, color: '#aaa', showMinLabel: true, showMaxLabel: true },
|
||||
splitLine: { show: true, lineStyle: { color: '#eee' } },
|
||||
splitNumber: 1,
|
||||
animation: false,
|
||||
scale: true,
|
||||
min: 'dataMin',
|
||||
max: 'dataMax',
|
||||
}
|
||||
}
|
||||
|
||||
// generate x axis format
|
||||
function makeXAxisOverview (gridIndex, type) {
|
||||
return {
|
||||
type: type,
|
||||
gridIndex: gridIndex,
|
||||
axisLine: { show: false, onZero: false, lineStyle: { color: '#aaa' } },
|
||||
axisTick: { show: false },
|
||||
axisLabel: { show: true, color: '#aaa', showMinLabel: true, showMaxLabel: true },
|
||||
splitLine: { show: false, lineStyle: { color: '#eee' } },
|
||||
scale: true,
|
||||
min: null,
|
||||
max: null,
|
||||
}
|
||||
}
|
||||
|
||||
// generate y axis format
|
||||
function makeYAxisOverview (gridIndex, type) {
|
||||
return {
|
||||
type: type,
|
||||
gridIndex: gridIndex,
|
||||
axisTick: { show: false },
|
||||
axisLine: { show: false }, // color: '#ccc' } },
|
||||
axisLabel: { show: true, color: '#aaa', showMinLabel: true, showMaxLabel: true },
|
||||
splitLine: { show: true, lineStyle: { color: '#eee' } },
|
||||
splitNumber: 1,
|
||||
animation: false,
|
||||
scale: true,
|
||||
min: 'dataMin',
|
||||
max: 'dataMax',
|
||||
}
|
||||
}
|
||||
|
||||
// get legend name
|
||||
function getLegendName (sourceList) {
|
||||
let legendName = ''
|
||||
// source only 2 device
|
||||
sourceList.forEach(source => {
|
||||
switch (source.name) {
|
||||
case 'Time':
|
||||
legendName += 'T'
|
||||
break
|
||||
case 'Neulive':
|
||||
switch (source.channel) {
|
||||
case 256:
|
||||
legendName += '' + source.id + '-X'
|
||||
break
|
||||
case 257:
|
||||
legendName += '' + source.id + '-Y'
|
||||
break
|
||||
case 258:
|
||||
legendName += '' + source.id + '-Z'
|
||||
break
|
||||
case 259:
|
||||
legendName += '' + source.id + '-Mag'
|
||||
break
|
||||
default:
|
||||
legendName += '' + source.id + 'CH' + String(parseInt(source.channel) + 1)
|
||||
break
|
||||
}
|
||||
break
|
||||
case 'Elite':
|
||||
switch (source.channel) {
|
||||
case 1:
|
||||
legendName += '' + source.id + '-I'
|
||||
break
|
||||
case 2:
|
||||
legendName += '' + source.id + '-V'
|
||||
break
|
||||
case 3:
|
||||
legendName += '' + source.id + '-R'
|
||||
break
|
||||
default:
|
||||
legendName += '' + source.id + 'CH' + source.channel
|
||||
break
|
||||
}
|
||||
break
|
||||
default:
|
||||
legendName += '' + source.id + 'CH' + source.channel
|
||||
break
|
||||
}
|
||||
legendName += '_'
|
||||
})
|
||||
legendName = legendName.substr(0, legendName.length - 1)
|
||||
return legendName
|
||||
}
|
||||
|
||||
// generate grid
|
||||
function makeGrid (index, length, chartID) {
|
||||
const _height = (82 / length) - 2 + '%'
|
||||
let _top
|
||||
if (chartID === 0) {
|
||||
_top = index * (82 / length) + 8 + '%'
|
||||
} else {
|
||||
_top = index * (82 / length) + 6 + '%'
|
||||
}
|
||||
const _left = '8%'
|
||||
const _right = '4%'
|
||||
return {
|
||||
index: index,
|
||||
top: _top,
|
||||
height: _height,
|
||||
left: _left,
|
||||
right: _right,
|
||||
series: [],
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
|
||||
/**
|
||||
* init data to chartData via chartID
|
||||
*
|
||||
* @param {object} chartAllData
|
||||
* @param {int} chartID : chart id
|
||||
* @param {int} gridLength : length of chart grid
|
||||
* @param {string} type
|
||||
* @param {string} device
|
||||
* @param {string} mode
|
||||
* @return {object} : chart data
|
||||
*/
|
||||
[typePath.init]: ({ state, getters, commit, dispatch }, payload) => {
|
||||
if (payload.chartAllData[payload.chartID] == null) {
|
||||
payload.chartAllData[payload.chartID] = newChart(payload.chartID)
|
||||
payload.chartAllData[payload.chartID].tooltip = newTooltip()
|
||||
payload.chartAllData[payload.chartID].chartType = payload.type
|
||||
payload.chartAllData[payload.chartID].chartDevice = payload.device
|
||||
payload.chartAllData[payload.chartID].chartMode = payload.mode
|
||||
|
||||
dispatch(typePath.updateGridList, { chartAllData: payload.chartAllData, chartID: payload.chartID, gridLength: payload.gridLength })
|
||||
return payload.chartAllData[payload.chartID]
|
||||
} else {
|
||||
return payload.chartAllData[payload.chartID]
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* init selectedChannel by metaIndex
|
||||
*
|
||||
* @param {int} metaIndex : chart id
|
||||
*/
|
||||
[typePath.initSelectedChannel]: ({ state, getters, commit, dispatch }, payload) => {
|
||||
const channelList = JSON.parse(state.metaList[payload.metaIndex].channels)
|
||||
state.selectedChannel = String(channelList[0])
|
||||
state.selectedChannelOptions = []
|
||||
channelList.forEach(function (item) {
|
||||
if (item < 256) {
|
||||
state.selectedChannelOptions.push({ label: String(item + 1), value: String(item) })
|
||||
} else if (item === 256) {
|
||||
state.selectedChannelOptions.push({ label: 'x', value: String(item) })
|
||||
} else if (item === 257) {
|
||||
state.selectedChannelOptions.push({ label: 'y', value: String(item) })
|
||||
} else if (item === 258) {
|
||||
state.selectedChannelOptions.push({ label: 'z', value: String(item) })
|
||||
} else if (item === 259) {
|
||||
state.selectedChannelOptions.push({ label: 'mag', value: String(item) })
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* update grid length by chart ID
|
||||
*
|
||||
* @param {object} chartAllData
|
||||
* @param {int} chartID
|
||||
* @param {int} gridLength : chart data (echarts options)
|
||||
*/
|
||||
[typePath.updateGridList]: async ({ state, getters, commit }, payload) => {
|
||||
payload.chartAllData[payload.chartID].grid = []
|
||||
for (let i = 0; i < payload.gridLength; i++) {
|
||||
payload.chartAllData[payload.chartID].grid.push(makeGrid(i, payload.gridLength, payload.chartID))
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* reset data from chartData via chartID
|
||||
*
|
||||
* @param {object} chartAllData
|
||||
* @param {int} chartID : chart id
|
||||
* @param {int} gridLength : length of chart grid
|
||||
* @return {object} : chart data
|
||||
*/
|
||||
[typePath.reset]: ({ state, getters, commit, dispatch }, payload) => {
|
||||
// delete
|
||||
for (const _series of payload.chartAllData[payload.chartID].series) {
|
||||
_series.data.length = 0
|
||||
_series.length = 0
|
||||
}
|
||||
delete payload.chartAllData[payload.chartID]
|
||||
dispatch(typePath.init, { chartAllData: payload.chartAllData, chartID: payload.chartID, gridLength: payload.gridLength })
|
||||
},
|
||||
|
||||
/**
|
||||
* clear all chart data
|
||||
*
|
||||
* @param {int} chartAllData
|
||||
*/
|
||||
[typePath.clear]: ({ state, getters, commit }, payload) => {
|
||||
for (const id in payload.chartAllData) {
|
||||
for (const _series of payload.chartAllData[id].series) {
|
||||
_series.data.length = 0
|
||||
_series.length = 0
|
||||
}
|
||||
delete payload.chartAllData[id]
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* update datazoom by chart ID
|
||||
*
|
||||
* @param {object} chartAllData
|
||||
* @param {int} chartID
|
||||
*/
|
||||
[typePath.updateDataZoom]: (state, payload) => {
|
||||
// update dataZoom AxisIndex list
|
||||
const dataZoomXAxisIndex = Array.apply(null, { length: payload.chartAllData[payload.chartID].xAxis.length }).map(Number.call, Number)
|
||||
const dataZoomYAxisIndex = Array.apply(null, { length: payload.chartAllData[payload.chartID].yAxis.length }).map(Number.call, Number)
|
||||
if (payload.chartAllData[payload.chartID].dataZoom == null) {
|
||||
payload.chartAllData[payload.chartID].dataZoom = newDataZoom()
|
||||
}
|
||||
if (payload.chartAllData[payload.chartID].dataZoom != null) {
|
||||
payload.chartAllData[payload.chartID].dataZoom[0].xAxisIndex = dataZoomXAxisIndex
|
||||
payload.chartAllData[payload.chartID].dataZoom[1].xAxisIndex = dataZoomXAxisIndex
|
||||
payload.chartAllData[payload.chartID].dataZoom[2].yAxisIndex = dataZoomYAxisIndex
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* register device-channel to chartData
|
||||
*
|
||||
* @param {object} chartAllData
|
||||
* @param {int} chartID : chart id
|
||||
* @param {int} gridIndex : index of grid
|
||||
* @param {int} deviceNameX
|
||||
* @param {int} deviceIDX
|
||||
* @param {int} channelX
|
||||
* @param {int} deviceNameY
|
||||
* @param {int} deviceIDY
|
||||
* @param {int} channelY
|
||||
* @return {object} : chart data
|
||||
*/
|
||||
[typePath.register]: ({ state, getters, commit, dispatch }, payload) => {
|
||||
const chartData = payload.chartAllData[payload.chartID]
|
||||
const sourceList = [
|
||||
{
|
||||
name: payload.deviceNameX,
|
||||
id: payload.deviceIDX,
|
||||
channel: payload.channelX,
|
||||
},
|
||||
{
|
||||
name: payload.deviceNameY,
|
||||
id: payload.deviceIDY,
|
||||
channel: payload.channelY,
|
||||
},
|
||||
]
|
||||
if (chartData == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
let xAxisType
|
||||
let yAxisType
|
||||
let xAxisSource
|
||||
let yAxisSource
|
||||
|
||||
const legendName = getLegendName(sourceList)
|
||||
|
||||
switch (sourceList[0].name) {
|
||||
case 'Time':
|
||||
xAxisType = 'time'
|
||||
xAxisSource = [-1, -1]
|
||||
break
|
||||
default:
|
||||
xAxisType = 'value'
|
||||
xAxisSource = [sourceList[0].id, sourceList[0].channel]
|
||||
break
|
||||
}
|
||||
switch (sourceList[1].name) {
|
||||
case 'Time':
|
||||
yAxisType = 'time'
|
||||
yAxisSource = [-1, -1]
|
||||
break
|
||||
default:
|
||||
yAxisType = 'value'
|
||||
yAxisSource = [sourceList[1].id, sourceList[1].channel]
|
||||
break
|
||||
}
|
||||
|
||||
// if AxisIndex != -1 then add new axis into list
|
||||
let _xAxisIndex = -1
|
||||
let _yAxisIndex = -1
|
||||
// the grid have exist, so just use the axis in grid
|
||||
for (let i = 0; i < chartData.xAxis.length; i++) {
|
||||
if (chartData.xAxis[i].gridIndex === payload.gridIndex) {
|
||||
_xAxisIndex = i
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < chartData.yAxis.length; i++) {
|
||||
if (chartData.yAxis[i].gridIndex === payload.gridIndex) {
|
||||
_yAxisIndex = i
|
||||
}
|
||||
}
|
||||
|
||||
// create new axis
|
||||
if (_xAxisIndex === -1) {
|
||||
if (payload.chartID === 0) {
|
||||
chartData.xAxis.push(makeXAxisOverview(payload.gridIndex, xAxisType))
|
||||
} else {
|
||||
chartData.xAxis.push(makeXAxis(payload.gridIndex, xAxisType))
|
||||
}
|
||||
_xAxisIndex = chartData.xAxis.length - 1
|
||||
}
|
||||
if (_yAxisIndex === -1) {
|
||||
if (payload.chartID === 0) {
|
||||
chartData.yAxis.push(makeYAxisOverview(payload.gridIndex, yAxisType))
|
||||
} else {
|
||||
chartData.yAxis.push(makeYAxis(payload.gridIndex, yAxisType))
|
||||
}
|
||||
_yAxisIndex = chartData.yAxis.length - 1
|
||||
}
|
||||
|
||||
// dispatch(typePath.updateDataZoom, { chartAllData: payload.chartAllData, chartID: payload.chartID })
|
||||
|
||||
// register series
|
||||
const _series = newSeries('line', legendName, _xAxisIndex, _yAxisIndex, xAxisSource, yAxisSource, null, null)
|
||||
chartData.series.push(_series)
|
||||
|
||||
// register series into grid
|
||||
const _axisList = []
|
||||
|
||||
sourceList.forEach((source, index) => {
|
||||
let _axis = 'X'
|
||||
if (index !== 0) {
|
||||
_axis = 'Y'
|
||||
}
|
||||
switch (source.name) {
|
||||
case 'Time':
|
||||
_axisList.push(_axis + ' AXIS = TIME')
|
||||
break
|
||||
case 'Neulive':
|
||||
_axisList.push(_axis + ' AXIS = NEULIVE ' + source.id + ' CHANNEL ' + source.channel)
|
||||
break
|
||||
case 'Elite':
|
||||
switch (source.channel) {
|
||||
case 1:
|
||||
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' CURRENT')
|
||||
break
|
||||
case 2:
|
||||
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' VOLTAGE')
|
||||
break
|
||||
case 3:
|
||||
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' RESISTANCE')
|
||||
break
|
||||
default:
|
||||
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' CHANNEL ' + source.channel)
|
||||
break
|
||||
}
|
||||
break
|
||||
default:
|
||||
_axisList.push(_axis + ' AXIS = DEVICE ' + source.id + ' CHANNEL ' + source.channel)
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
const _gridSeries = {
|
||||
name: legendName,
|
||||
xAxis: _axisList[0],
|
||||
yAxis: _axisList[1],
|
||||
}
|
||||
|
||||
chartData.grid[payload.gridIndex].series.push(_gridSeries)
|
||||
|
||||
return chartData
|
||||
},
|
||||
|
||||
// /**
|
||||
// * remove device-channel from chart TODO
|
||||
// *
|
||||
// * @param {object} chartAllData
|
||||
// * @param {int} chartID
|
||||
// * @param {int} legendName
|
||||
// * @return {object} : chart data
|
||||
// */
|
||||
// [typePath.remove]: ({ state, getters, commit }, payload) => {
|
||||
// const chartData = getters.getDataByIDChart(payload.chartID)
|
||||
// if (chartData == null || chartData.legend.data.length === 0) {
|
||||
// return false
|
||||
// }
|
||||
|
||||
// let _xAxisIndex = -1
|
||||
// let _yAxisIndex = -1
|
||||
|
||||
// // remove legend
|
||||
// const _legendIndex = chartData.legend.data.indexOf(payload.legendName)
|
||||
// console.log(_legendIndex)
|
||||
// if (_legendIndex >= 0) {
|
||||
// chartData.legend.data.splice(chartData.legend.data.indexOf(payload.legendName), 1)
|
||||
// } else {
|
||||
// return false
|
||||
// }
|
||||
// // remove series
|
||||
// for (let i = 0; i < chartData.series.length; i++) {
|
||||
// if (chartData.series[i].name === payload.legendName) {
|
||||
// _xAxisIndex = chartData.series[i].xAxisIndex
|
||||
// _yAxisIndex = chartData.series[i].yAxisIndex
|
||||
// chartData.series.splice(i, 1)
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// // remove grid series name
|
||||
// const _gridIndex = chartData.xAxis[_xAxisIndex].gridIndex
|
||||
// for (let i = 0; i < chartData.grid[_gridIndex].series.length; i++) {
|
||||
// if (chartData.grid[_gridIndex].series[i] === payload.legendName) {
|
||||
// chartData.grid[_gridIndex].series.splice(i, 1)
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// for (let i = 0; i < chartData.grid.length; i++) {
|
||||
// if (chartData.grid[i].name === payload.legendName) {
|
||||
// _xAxisIndex = chartData.series[i].xAxisIndex
|
||||
// _yAxisIndex = chartData.series[i].yAxisIndex
|
||||
// chartData.series.splice(i, 1)
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// chartData.series.forEach(series => {
|
||||
// if (series.xAxisIndex === _xAxisIndex) {
|
||||
// _xAxisIndex = -1
|
||||
// }
|
||||
// if (series.yAxisIndex === _yAxisIndex) {
|
||||
// _yAxisIndex = -1
|
||||
// }
|
||||
// })
|
||||
// // remove xAxis
|
||||
// if (_xAxisIndex !== -1) {
|
||||
// chartData.xAxis.splice(_xAxisIndex, 1)
|
||||
// chartData.series.forEach(series => {
|
||||
// if (series.xAxisIndex > _xAxisIndex) {
|
||||
// series.xAxisIndex--
|
||||
// }
|
||||
// })
|
||||
// chartData.dataZoom[0].xAxisIndex.pop()
|
||||
// }
|
||||
// // remove yAxis
|
||||
// if (_yAxisIndex !== -1) {
|
||||
// chartData.yAxis.splice(_yAxisIndex, 1)
|
||||
// chartData.series.forEach(series => {
|
||||
// if (series.yAxisIndex > _yAxisIndex) {
|
||||
// series.yAxisIndex--
|
||||
// }
|
||||
// })
|
||||
// chartData.dataZoom[2].yAxisIndex.pop()
|
||||
// }
|
||||
|
||||
// console.log(chartData)
|
||||
// return true
|
||||
// },
|
||||
|
||||
}
|
||||
|
||||
export default actions
|
||||
@@ -0,0 +1,9 @@
|
||||
import chartAct from './chartAct'
|
||||
import metaAct from './metaAct'
|
||||
import recAct from './recAct'
|
||||
|
||||
export default {
|
||||
...chartAct,
|
||||
...metaAct,
|
||||
...recAct,
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import types from '@/store/modules/analysis/spike/types'
|
||||
|
||||
const typePath = types.meta
|
||||
|
||||
const metaActs = {
|
||||
/**
|
||||
* init meta
|
||||
*
|
||||
* @param {Array} metaIDList
|
||||
* @param {objuct} api
|
||||
* @return {object} : meta list info
|
||||
*/
|
||||
[typePath.init]: async ({ state, getters, commit }, payload) => {
|
||||
const promises = payload.metaIDList.map(async id => {
|
||||
const metaRes = await payload.api.meta.getByID(id)
|
||||
return metaRes.data[0]
|
||||
})
|
||||
const list = await Promise.all(promises)
|
||||
commit(typePath.set, { list: list })
|
||||
},
|
||||
}
|
||||
|
||||
export default metaActs
|
||||
@@ -0,0 +1,131 @@
|
||||
import types from '@/store/modules/analysis/spike/types'
|
||||
|
||||
const typePath = types.rec
|
||||
|
||||
const recActs = {
|
||||
/**
|
||||
* get rec by list index
|
||||
*
|
||||
* @param {objuct} api
|
||||
* @return {object} : rec info
|
||||
*/
|
||||
[typePath.init]: async ({ state, getters, commit }, payload) => {
|
||||
const metaList = getters.getAllMeta
|
||||
const _rec = {}
|
||||
metaList.forEach(meta => {
|
||||
_rec[meta.id] = {}
|
||||
JSON.parse(meta.channels).forEach(ch => {
|
||||
_rec[meta.id][ch] = {
|
||||
1: [],
|
||||
10: [],
|
||||
100: [],
|
||||
1000: [],
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const getRawInfo = metaList.map(async meta => {
|
||||
const getData = JSON.parse(meta.channels).map(async ch => {
|
||||
const res = await payload.api.raw.getAttrByParent(ch, meta.id, 'id-start_time-end_time')
|
||||
res.data.forEach(_data => {
|
||||
_data.load = false
|
||||
_data.data = []
|
||||
if (parseInt(_data.end_time) <= parseInt(meta.time_duration)) {
|
||||
if (parseInt(_data.end_time) < 0) {
|
||||
_data.end_time = parseInt(meta.time_duration)
|
||||
}
|
||||
_rec[meta.id][ch][1].push(_data)
|
||||
}
|
||||
})
|
||||
return res.data
|
||||
})
|
||||
return await Promise.all(getData)
|
||||
})
|
||||
await Promise.all(getRawInfo)
|
||||
|
||||
const getMiniInfo = metaList.map(async meta => {
|
||||
const getData = JSON.parse(meta.channels).map(async ch => {
|
||||
const miniIDs = Object.values(meta.mini_data[ch])
|
||||
const combineMiniIDs = [].concat.apply([], miniIDs)
|
||||
|
||||
for (const id of combineMiniIDs) {
|
||||
const res = await payload.api.mini.getAttrByID(ch, id, 'id-start_time-end_time-scale')
|
||||
res.data.forEach(_data => {
|
||||
_data.load = false
|
||||
_data.data = []
|
||||
if (parseInt(_data.end_time) <= parseInt(meta.time_duration)) {
|
||||
if (parseInt(_data.end_time) < 0) {
|
||||
_data.end_time = parseInt(meta.time_duration)
|
||||
}
|
||||
_rec[meta.id][ch][parseInt(_data.scale)].push(_data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// const res = await payload.api.mini.getAttrByParent(ch, meta.id, 'id-start_time-end_time-scale')
|
||||
// res.data.forEach(_data => {
|
||||
// _data.load = false
|
||||
// _data.data = []
|
||||
// if (_data.end_time < 0) {
|
||||
// _data.end_time = meta.time_duration
|
||||
// }
|
||||
// _rec[meta.id][ch][parseInt(_data.scale)].push(_data)
|
||||
// })
|
||||
// return res.data
|
||||
})
|
||||
return await Promise.all(getData)
|
||||
})
|
||||
await Promise.all(getMiniInfo)
|
||||
commit(typePath.set, { data: _rec })
|
||||
},
|
||||
|
||||
/**
|
||||
* into data to rec
|
||||
*
|
||||
* @param {int} index
|
||||
* @param {int} metaID
|
||||
* @param {int} channel
|
||||
* @param {int} scale
|
||||
* @param {object} data
|
||||
*/
|
||||
[typePath.intoData]: async ({ state, getters, commit }, payload) => {
|
||||
commit(typePath.updateDataByIndex, {
|
||||
index: payload.index,
|
||||
metaID: payload.metaID,
|
||||
channel: payload.channel,
|
||||
scale: payload.scale,
|
||||
data: payload.data,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* into data to rec
|
||||
*
|
||||
* @param {int} meta
|
||||
* @param {str} device
|
||||
*/
|
||||
[typePath.initDisplaySetting]: async ({ state, getters, commit }, payload) => {
|
||||
switch (payload.device) {
|
||||
case 'Neulive':
|
||||
commit(typePath.initDisplaySettingNeulive, {
|
||||
meta: payload.meta,
|
||||
})
|
||||
break
|
||||
case 'Elite':
|
||||
commit(typePath.initDisplaySettingElite, {
|
||||
meta: payload.meta,
|
||||
})
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
},
|
||||
|
||||
[typePath.updateDisplaySetting]: async ({ state, getters, commit }, payload) => {
|
||||
commit(typePath.updateDisplaySetting, {
|
||||
updateObject: payload.updateObject,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
export default recActs
|
||||
@@ -0,0 +1,9 @@
|
||||
import metaGet from './metaGet'
|
||||
import recGet from './recGet'
|
||||
import { getField } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
...metaGet,
|
||||
...recGet,
|
||||
getField,
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import types from '@/store/modules/analysis/spike/types'
|
||||
|
||||
const typePath = types.meta
|
||||
|
||||
const metaGets = {
|
||||
/**
|
||||
* get meta by list index
|
||||
*
|
||||
* @param {int} index
|
||||
* @return {object} : meta info
|
||||
*/
|
||||
[typePath.getByIndex]: (state) => (index) => {
|
||||
if (index == null || state.chartData[index] == null) {
|
||||
return null
|
||||
}
|
||||
return state.metaList[index]
|
||||
},
|
||||
|
||||
/**
|
||||
* get meta by id
|
||||
*
|
||||
* @param {int} id
|
||||
* @return {object} : meta info
|
||||
*/
|
||||
[typePath.getByID]: (state) => (id) => {
|
||||
state.metaList.forEach(meta => {
|
||||
if (meta.id === id) {
|
||||
return meta
|
||||
}
|
||||
})
|
||||
return null
|
||||
},
|
||||
|
||||
/**
|
||||
* get all meta info
|
||||
*
|
||||
* @return {Array} : meta list
|
||||
*/
|
||||
[typePath.getAll]: (state) => {
|
||||
return state.metaList
|
||||
},
|
||||
}
|
||||
|
||||
export default metaGets
|
||||
@@ -0,0 +1,61 @@
|
||||
import types from '@/store/modules/analysis/spike/types'
|
||||
|
||||
const typePath = types.rec
|
||||
|
||||
const recGets = {
|
||||
/**
|
||||
* get rec by meta
|
||||
*
|
||||
* @return {object} : rec data
|
||||
*/
|
||||
[typePath.getByMeta]: (state) => (meta) => {
|
||||
return state.recInfo[meta]
|
||||
},
|
||||
|
||||
/**
|
||||
* get all rec data
|
||||
* @return {Object} : rec data
|
||||
*/
|
||||
[typePath.getAll]: (state) => {
|
||||
return state.recInfo
|
||||
},
|
||||
|
||||
/**
|
||||
* get cycle data mapping
|
||||
* @param {string} : meta ID
|
||||
* @param {int} : cycle channel index
|
||||
* @param {object} : cycleDataList, list value: object
|
||||
* @return {object} : cycle mapping
|
||||
*/
|
||||
[typePath.getCycleDict]: (state) => (cycleDataList) => {
|
||||
// get cycle data
|
||||
// const cycleDataList = state.recInfo[metaID][cycleDataID][state.currentScale]
|
||||
const cycleDataListNum = cycleDataList.length
|
||||
var cycleDict = {}
|
||||
var cycleStartTime = 0
|
||||
var cycleEndTime = 0
|
||||
var currentCycleIndex = 0
|
||||
for (let i = 0; i < cycleDataListNum; i++) {
|
||||
const cycleDataArray = cycleDataList[i].data
|
||||
for (let index = 0; index < cycleDataArray.length; index++) {
|
||||
const value = cycleDataArray[index]
|
||||
const time = parseInt(value[0])
|
||||
const cycleIndex = parseInt(value[1])
|
||||
if (cycleIndex === currentCycleIndex) {
|
||||
if (currentCycleIndex in cycleDict) {
|
||||
cycleEndTime = time
|
||||
cycleDict[cycleIndex][1] = cycleEndTime
|
||||
} else {
|
||||
cycleDict[cycleIndex] = [cycleStartTime, cycleEndTime]
|
||||
}
|
||||
} else {
|
||||
cycleStartTime = time
|
||||
currentCycleIndex++
|
||||
}
|
||||
}
|
||||
}
|
||||
return cycleDict
|
||||
},
|
||||
}
|
||||
|
||||
export default recGets
|
||||
@@ -0,0 +1,12 @@
|
||||
import actions from './actions'
|
||||
import getters from './getters'
|
||||
import mutations from './mutations'
|
||||
import state from './state'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: state,
|
||||
getters: getters,
|
||||
actions: actions,
|
||||
mutations: mutations,
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
import types from '@/store/modules/analysis/spike/types'
|
||||
|
||||
const typePath = types.chart
|
||||
|
||||
// get legend name
|
||||
function getLegendName (sourceList) {
|
||||
let legendName = ''
|
||||
// source only 2 device
|
||||
sourceList.forEach(source => {
|
||||
switch (source.name) {
|
||||
case 'Time':
|
||||
legendName += 'T'
|
||||
break
|
||||
case 'Neulive':
|
||||
switch (source.channel) {
|
||||
case 256:
|
||||
legendName += '' + source.id + '-X'
|
||||
break
|
||||
case 257:
|
||||
legendName += '' + source.id + '-Y'
|
||||
break
|
||||
case 258:
|
||||
legendName += '' + source.id + '-Z'
|
||||
break
|
||||
case 259:
|
||||
legendName += '' + source.id + '-Mag'
|
||||
break
|
||||
default:
|
||||
legendName += '' + source.id + 'CH' + String(parseInt(source.channel) + 1)
|
||||
break
|
||||
}
|
||||
break
|
||||
case 'Elite':
|
||||
switch (source.channel) {
|
||||
case 1:
|
||||
legendName += '' + source.id + '-I'
|
||||
break
|
||||
case 2:
|
||||
legendName += '' + source.id + '-V'
|
||||
break
|
||||
case 3:
|
||||
legendName += '' + source.id + '-R'
|
||||
break
|
||||
default:
|
||||
legendName += '' + source.id + 'CH' + source.channel
|
||||
break
|
||||
}
|
||||
break
|
||||
default:
|
||||
legendName += '' + source.id + 'CH' + source.channel
|
||||
break
|
||||
}
|
||||
legendName += '_'
|
||||
})
|
||||
legendName = legendName.substr(0, legendName.length - 1)
|
||||
return legendName
|
||||
}
|
||||
|
||||
const chartMutations = {
|
||||
/**
|
||||
* update label formatter
|
||||
*
|
||||
* @param {int} chartID
|
||||
* @param {string} axis ('x' or 'y')
|
||||
* @param {int} axisIndex
|
||||
* @param {int} channel // use for checking whether it is 3-axis
|
||||
*/
|
||||
[typePath.updateAxisLabel]: (state, payload) => {
|
||||
if (payload.axis === 'x') {
|
||||
const axisLabel = state.chartData[payload.chartID].xAxis[payload.axisIndex].axisLabel
|
||||
axisLabel.formatter = function (val) {
|
||||
let label = ''
|
||||
const hour = Math.floor(val / 3.6e9)
|
||||
const minute = Math.floor((val % 3.6e9) / 1000000 / 60)
|
||||
const second = Math.floor((val % 6e7) / 1000000)
|
||||
const millisecond = Math.floor((val % 1e6) / 1000)
|
||||
const microsecond = Math.floor(val % 1e6) - 1000 * millisecond
|
||||
if (hour > 0) {
|
||||
label += hour + ' h '
|
||||
}
|
||||
if (minute > 0) {
|
||||
label += minute + ' m '
|
||||
}
|
||||
if (second > 0) {
|
||||
label += second + ' s '
|
||||
}
|
||||
if (millisecond > 0) {
|
||||
label += millisecond + ' ms '
|
||||
}
|
||||
if (microsecond > 0 && hour === 0 && minute === 0 && second === 0) {
|
||||
label += microsecond + ' µs '
|
||||
}
|
||||
return label
|
||||
}
|
||||
} else if (payload.axis === 'y') {
|
||||
const axisLabel = state.chartData[payload.chartID].yAxis[payload.axisIndex].axisLabel
|
||||
axisLabel.formatter = function (val) {
|
||||
let label
|
||||
if (payload.channel < 256) {
|
||||
const num = String(val)
|
||||
label = num + 'µV'
|
||||
} else {
|
||||
label = String(val.toFixed(2))
|
||||
}
|
||||
return label
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* turn on/off axis event handler
|
||||
*
|
||||
* @param {int} chartID
|
||||
* @param {string} axis ('x' or 'y')
|
||||
* @param {bool} status (on/off)
|
||||
*/
|
||||
[typePath.updateAxisEventHandler]: (state, payload) => {
|
||||
let _axis
|
||||
if (payload.axis === 'x') {
|
||||
_axis = state.chartData[payload.chartID].xAxis
|
||||
} else if (payload.axis === 'y') {
|
||||
_axis = state.chartData[payload.chartID].yAxis
|
||||
}
|
||||
const len = _axis.length
|
||||
if (payload.status === 'on') {
|
||||
for (let i = 0; i < len; i++) {
|
||||
_axis[i].triggerEvent = true
|
||||
}
|
||||
} else if (payload.status === 'off') {
|
||||
for (let i = 0; i < len; i++) {
|
||||
_axis[i].triggerEvent = false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* update axis value min & max
|
||||
*
|
||||
* @param {int} chartID
|
||||
* @param {string} axis ('x' or 'y')
|
||||
* @param {int} axisIndex
|
||||
* @param {float} minVal
|
||||
* @param {float} maxVal
|
||||
*/
|
||||
[typePath.updateAxisValMinMax]: (state, payload) => {
|
||||
let grid
|
||||
if (payload.axis === 'x') {
|
||||
grid = state.chartData[payload.chartID].xAxis[payload.axisIndex]
|
||||
} else if (payload.axis === 'y') {
|
||||
grid = state.chartData[payload.chartID].yAxis[payload.axisIndex]
|
||||
}
|
||||
if (payload.minVal !== '') {
|
||||
grid.min = payload.minVal
|
||||
} else {
|
||||
grid.min = 'dataMin'
|
||||
}
|
||||
if (payload.maxVal !== '') {
|
||||
grid.max = payload.maxVal
|
||||
} else {
|
||||
grid.max = 'dataMax'
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* update series by cycle
|
||||
*
|
||||
* @param {int} chartID
|
||||
* @param {int} seriesIndex
|
||||
* @param {array} data
|
||||
*/
|
||||
[typePath.updateSeries]: (state, payload) => {
|
||||
state.chartData[payload.chartID].series[payload.seriesIndex].data = payload.data
|
||||
},
|
||||
|
||||
/**
|
||||
* update registered chartData
|
||||
*
|
||||
* @param {object} chartAllData
|
||||
* @param {int} chartID : chart id
|
||||
* @param {int} gridIndex : index of grid
|
||||
* @param {int} deviceNameX
|
||||
* @param {int} deviceIDX
|
||||
* @param {int} channelX
|
||||
* @param {int} deviceNameY
|
||||
* @param {int} deviceIDY
|
||||
* @param {int} channelY
|
||||
* @return {object} : chart data
|
||||
*/
|
||||
[typePath.updateRegistered]: ({ state, getters, commit, dispatch }, payload) => {
|
||||
const chartData = payload.chartAllData[payload.chartID]
|
||||
const sourceList = [
|
||||
{
|
||||
name: payload.deviceNameX,
|
||||
id: payload.deviceIDX,
|
||||
channel: payload.channelX,
|
||||
},
|
||||
{
|
||||
name: payload.deviceNameY,
|
||||
id: payload.deviceIDY,
|
||||
channel: payload.channelY,
|
||||
},
|
||||
]
|
||||
if (chartData == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
const legendName = getLegendName(sourceList)
|
||||
|
||||
// register legendName
|
||||
if (chartData.legend.data.indexOf(legendName) >= 0) {
|
||||
// have been registered
|
||||
return false
|
||||
}
|
||||
|
||||
// push legendName
|
||||
chartData.legend.data[payload.gridIndex] = legendName
|
||||
|
||||
// register series into grid
|
||||
const _axisList = []
|
||||
|
||||
sourceList.forEach((source, index) => {
|
||||
let _axis = 'X'
|
||||
if (index !== 0) {
|
||||
_axis = 'Y'
|
||||
}
|
||||
switch (source.name) {
|
||||
case 'Time':
|
||||
_axisList.push(_axis + ' AXIS = TIME')
|
||||
break
|
||||
case 'Neulive':
|
||||
_axisList.push(_axis + ' AXIS = NEULIVE ' + source.id + ' CHANNEL ' + source.channel)
|
||||
break
|
||||
case 'Elite':
|
||||
switch (source.channel) {
|
||||
case 1:
|
||||
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' CURRENT')
|
||||
break
|
||||
case 2:
|
||||
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' VOLTAGE')
|
||||
break
|
||||
case 3:
|
||||
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' RESISTANCE')
|
||||
break
|
||||
default:
|
||||
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' CHANNEL ' + source.channel)
|
||||
break
|
||||
}
|
||||
break
|
||||
default:
|
||||
_axisList.push(_axis + ' AXIS = DEVICE ' + source.id + ' CHANNEL ' + source.channel)
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
const _gridSeries = {
|
||||
name: legendName,
|
||||
xAxis: _axisList[0],
|
||||
yAxis: _axisList[1],
|
||||
}
|
||||
|
||||
chartData.grid[payload.gridIndex].series[payload.gridIndex] = _gridSeries
|
||||
chartData.series[payload.gridIndex].name = legendName
|
||||
|
||||
return chartData
|
||||
},
|
||||
|
||||
/**
|
||||
* update axis 間距刻度數量
|
||||
*
|
||||
* @param {int} chartID
|
||||
* @param {string} axis ('x' or 'y')
|
||||
*/
|
||||
[typePath.updateAxisSplitNumber]: (state, payload) => {
|
||||
if (payload.axis === 'x') {
|
||||
const axis = state.chartData[payload.chartID].xAxis
|
||||
const len = axis.length
|
||||
for (let i = 0; i < len; i++) {
|
||||
axis[i].splitNumber = 5
|
||||
}
|
||||
} else if (payload.axis === 'y') {
|
||||
const axis = state.chartData[payload.chartID].yAxis
|
||||
const len = axis.length
|
||||
let splitNum
|
||||
if (len === 1) {
|
||||
splitNum = 5
|
||||
} else if (len > 1 && len <= 4) {
|
||||
splitNum = 3
|
||||
} else if (len > 4) {
|
||||
splitNum = 1
|
||||
}
|
||||
for (let i = 0; i < len; i++) {
|
||||
axis[i].splitNumber = splitNum
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* update chart sampling method
|
||||
*
|
||||
* @param {int} chartID
|
||||
* @param {int} seriesIndex
|
||||
* @param {object} method
|
||||
*/
|
||||
[typePath.updateChartSampling]: (state, payload) => {
|
||||
state.chartData[payload.chartID].series[payload.seriesIndex].sampling = payload.method
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
export default chartMutations
|
||||
@@ -0,0 +1,11 @@
|
||||
import chartMut from './chartMut'
|
||||
import metaMut from './metaMut'
|
||||
import recMut from './recMut'
|
||||
import { updateField } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
...chartMut,
|
||||
...metaMut,
|
||||
...recMut,
|
||||
updateField,
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import types from '@/store/modules/analysis/spike/types'
|
||||
|
||||
const typePath = types.meta
|
||||
|
||||
const metaMutations = {
|
||||
/**
|
||||
* set meta list
|
||||
*
|
||||
*/
|
||||
[typePath.set]: async (state, payload) => {
|
||||
state.metaList.length = 0
|
||||
state.metaList = payload.list
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the meta info by index
|
||||
*
|
||||
* @param {number} index
|
||||
* @param {any} item
|
||||
*/
|
||||
[typePath.updateByIndex]: function (state, payload) {
|
||||
for (const item in payload) {
|
||||
if (item !== 'index') {
|
||||
state.metaList[payload.index][item] = payload[item]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
export default metaMutations
|
||||
@@ -0,0 +1,41 @@
|
||||
import types from '@/store/modules/analysis/spike/types'
|
||||
|
||||
const typePath = types.rec
|
||||
|
||||
const recMutations = {
|
||||
/**
|
||||
* set rec list
|
||||
*
|
||||
* @param {object} data
|
||||
*/
|
||||
[typePath.set]: async (state, payload) => {
|
||||
state.recInfo = payload.data
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the rec info by index
|
||||
*
|
||||
* @param {any} item
|
||||
*/
|
||||
[typePath.update]: function (state, payload) {
|
||||
for (const item in payload) {
|
||||
state.recInfo[item] = payload[item]
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* update data rec
|
||||
*
|
||||
* @param {int} index
|
||||
* @param {int} metaID
|
||||
* @param {int} channel
|
||||
* @param {int} scale
|
||||
* @param {object} data
|
||||
*/
|
||||
[typePath.updateDataByIndex]: function (state, payload) {
|
||||
state.recInfo[payload.metaID][payload.channel][payload.scale][payload.index].data = payload.data
|
||||
state.recInfo[payload.metaID][payload.channel][payload.scale][payload.index].load = true
|
||||
},
|
||||
}
|
||||
|
||||
export default recMutations
|
||||
@@ -0,0 +1,22 @@
|
||||
function newState () {
|
||||
return {
|
||||
recInfo: {},
|
||||
metaList: [],
|
||||
chartData: {},
|
||||
chartOverviewData: {},
|
||||
chartDetailData: {},
|
||||
|
||||
selectedChannel: '',
|
||||
selectedChannelOptions: [],
|
||||
cutoffFreq: 300,
|
||||
filterOrder: 4,
|
||||
selectedThreshold: 'over',
|
||||
upperThreshold: 68,
|
||||
lowerThreshold: 0,
|
||||
waveLength: 1600,
|
||||
preThreshold: 800,
|
||||
refractoryPeriod: 800,
|
||||
}
|
||||
}
|
||||
|
||||
export default newState
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
const types = {
|
||||
chart: {
|
||||
init: 'initChart',
|
||||
initSelectedChannel: 'initSelectedChannelChart',
|
||||
reset: 'resetChart',
|
||||
register: 'registerChart',
|
||||
remove: 'removeChart',
|
||||
clear: 'clearChart',
|
||||
|
||||
getDataByID: 'getDataByIDChart',
|
||||
getAllData: 'getAllDataChart',
|
||||
|
||||
setChartData: 'setChartDataChart',
|
||||
setTooltip: 'setTooltipChart',
|
||||
setMarkArea: 'setMarkAreaChart',
|
||||
setMarkAreaData: 'setMarkAreaDataChart',
|
||||
setDataZoom: 'setDataZoomChart',
|
||||
updateDataZoom: 'updateDataZoomChart',
|
||||
updateGridList: 'updateGridListChart',
|
||||
pushSeries: 'pushSeriesChart',
|
||||
pushAxis: 'pushAxisChart',
|
||||
pushLegendName: 'pushLegendNameChart',
|
||||
pushGridSeries: 'pushGridSeriesChart',
|
||||
deleteByID: 'deleteByIDChart',
|
||||
update: 'updateChart',
|
||||
updateSeries: 'updateSeriesChart',
|
||||
updateAxis: 'updateAxisChart',
|
||||
updateSeriesData: 'updateSeriesDataChart',
|
||||
updateAxisLabel: 'updateAxisLabelChart',
|
||||
updateAxisEventHandler: 'updateAxisEventHandlerChart',
|
||||
updateAxisValMinMax: 'updateAxisValMinMaxChart',
|
||||
updateRegistered: 'updateRegisteredChart',
|
||||
updateAxisSplitNumber: 'updateAxisSplitNumberChart',
|
||||
updateChartSampling: 'updateChartSamplingChart',
|
||||
},
|
||||
meta: {
|
||||
init: 'initMeta',
|
||||
|
||||
set: 'setMeta',
|
||||
setByApi: 'setByApiMeta',
|
||||
updateByIndex: 'updateByIndexMeta',
|
||||
|
||||
getByIndex: 'getByIndexMeta',
|
||||
getByID: 'getByIDMeta',
|
||||
getAll: 'getAllMeta',
|
||||
},
|
||||
rec: {
|
||||
init: 'initRec',
|
||||
intoData: 'intoDataRec',
|
||||
initDisplaySetting: 'initDisplaySettingRec',
|
||||
initDisplaySettingNeulive: 'initDisplaySettingNeuliveRec',
|
||||
initDisplaySettingElite: 'initDisplaySettingEliteRec',
|
||||
|
||||
set: 'setRec',
|
||||
update: 'updateRec',
|
||||
updateDataByIndex: 'updateDataByIndexRec',
|
||||
updateDisplaySetting: 'updateDisplaySettingRec',
|
||||
|
||||
getAll: 'getAllRec',
|
||||
getCycleDict: 'getCycleDictRec',
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
export default types
|
||||
Reference in New Issue
Block a user