Compare commits

...

10 Commits

16 changed files with 607 additions and 317 deletions
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

@@ -1,84 +1,84 @@
<template>
<div class="devices-overview">
<div>
<va-item>
<va-item-section style='text-align: center;'>
<p> Filename: </p>
<p> {{ filename }} </p>
</va-item-section>
<va-item-section style='text-align: center;'>
<va-button flat small color="gray" icon="fa fa-download" @click.stop="downloadCSV()"/>
<va-button flat small color="gray" icon="fa fa-pencil" @click.stop="editFileConfirm()"/>
<va-button flat small color="gray" icon="fa fa-trash" @click.stop="deleteFileConfirm()"/>
</va-item-section>
<va-item-section style='text-align: center;'>
<p> Current resample: </p>
<p> {{ currentScale }} to 1 </p>
</va-item-section>
<va-item-section>
X axis
<va-select
:label="''"
v-model="channelXSelect"
textBy="description"
:options="channelXOptions"
/>
</va-item-section>
<va-item-section>
X axis scale
<va-select
:label="''"
v-model="scaleXSelect"
textBy="description"
:options="scaleOptions"
/>
</va-item-section>
<va-item-section>
X axis unit
<va-select
:label="''"
v-model="valueFormatX"
textBy="unit"
:options="valueFormatOptions[channelXSelect.id]"
/>
</va-item-section>
<va-item-section>
Y axis
<va-select
:label="''"
v-model="channelYSelect"
textBy="description"
:options="channelYOptions"
/>
</va-item-section>
<va-item-section>
Y axis scale
<va-select
:label="''"
v-model="scaleYSelect"
textBy="description"
:options="scaleOptions"
/>
</va-item-section>
<va-item-section>
Y axis unit
<va-select
:label="''"
v-model="valueFormatY"
textBy="unit"
:options="valueFormatOptions[channelYSelect.id]"
/>
</va-item-section>
</va-item>
<va-card>
<div>
<div class="block">
<va-button flat small color="gray" icon="fa fa-file-text-o" @click.stop="editFileConfirm()"> {{ filename }} </va-button>
<va-button flat small color="gray" icon="fa fa-download" @click.stop="downloadCSV()"/>
<va-button flat small color="gray" icon="fa fa-trash" @click.stop="deleteFileConfirm()"/>
</div>
<span class="block"> Resample: {{ currentScale }} to 1 </span>
<span class="block"> X axis </span>
<div class="selected_block">
<va-select
:label="''"
v-model="channelXSelect"
textBy="description"
:options="channelXOptions"
:noClear="true"
/>
</div>
<span class="block"> X axis scale </span>
<div class="selected_block">
<va-select
:label="''"
v-model="scaleXSelect"
textBy="description"
:options="scaleOptions"
:noClear="true"
/>
</div>
<span class="block"> X axis unit </span>
<div class="selected_block">
<va-select
:label="''"
v-model="valueFormatX"
textBy="unit"
:options="valueFormatOptions[channelXSelect.id]"
:noClear="true"
/>
</div>
<span class="block"> Y axis </span>
<div class="selected_block">
<va-select
:label="''"
v-model="channelYSelect"
textBy="description"
:options="channelYOptions"
:noClear="true"
/>
</div>
<span class="block"> Y axis scale </span>
<div class="selected_block">
<va-select
:label="''"
v-model="scaleYSelect"
textBy="description"
:options="scaleOptions"
:noClear="true"
/>
</div>
<span class="block"> Y axis unit </span>
<div class="selected_block">
<va-select
:label="''"
v-model="valueFormatY"
textBy="unit"
:options="valueFormatOptions[channelYSelect.id]"
:noClear="true"
/>
</div>
</div>
<va-input
v-if="isNeedCycle"
v-model="showWhichCycles"
@change="reDraw"
:label="$t('See which cycles (separate by comma, e.g. 1,2,3)')"
/>
<elite-replay-chart :ref="'chart_detail'" @dblclick.native="distribute()" :cardheight="'71vh'" :data="chartDetailData" @dataZoomEvent="dataZoomEvent($event)"/>
<va-card :title="$t('Parameter')">
<va-input
v-if="isNeedCycle"
v-model="showWhichCycles"
@change="reDraw"
:label="$t('See which cycles (separate by comma, e.g. 1,2,3)')"
/>
<elite-replay-chart :ref="'chart_detail'" @dblclick.native="distribute()" :cardheight="'71vh'" :data="chartDetailData" @dataZoomEvent="dataZoomEvent($event)"/>
Parameter
<va-tree-root>
<va-tree-category label="AxisValueRangeSetting">
<div>
@@ -174,7 +174,7 @@ import { download } from '@/data/download/Download'
import { exportData } from '@/data/export/export'
import types from '@/store/modules/analysis/replay/elite/types'
import { mapFields } from 'vuex-map-fields'
import { trimValueArray, getValueArrayMinAndMax } from '@/data/tool'
import { convertValueArrayScale, getValueArrayMinAndMax } from '@/data/tool'
import { debounce } from 'lodash'
export default {
@@ -364,15 +364,15 @@ export default {
}
switch (chart) {
case 'detail':
this.$refs.chart_detail.$children[0].$children[0].showLoading(loadStyle)
this.$refs.chart_detail.showLoading(loadStyle)
break
default:
this.$refs.chart_detail.$children[0].$children[0].showLoading(loadStyle)
this.$refs.chart_detail.showLoading(loadStyle)
break
}
},
hideChartLoading: function () {
this.$refs.chart_detail.$children[0].$children[0].hideLoading()
this.$refs.chart_detail.hideLoading()
},
getData: async function (scale, id, channel, meta) {
if (scale === 1) {
@@ -627,7 +627,7 @@ export default {
})
}
console.assert(dataXList.length === dataYList.length) // [todo] need align 2 channel data?
console.assert(dataXList.length === dataYList.length)
let dataX = []
let dataY = []
if (scale >= 1) {
@@ -661,7 +661,7 @@ export default {
this.chartDetailData.series.forEach((series, index) => {
if (series.yAxisSource[0] === metaName && series.yAxisSource[1] === channelY) {
series.data = JSON.parse(JSON.stringify(cloneData))
this.$refs.chart_detail.$children[0].$children[0].appendData({
this.$refs.chart_detail.appendData({
seriesIndex: index,
data: series.data,
})
@@ -720,7 +720,7 @@ export default {
})
return data
}
this.$refs.chart_detail.$children[0].$children[0].appendData({
this.$refs.chart_detail.appendData({
seriesIndex: index,
data: getNewDataList(deStartIndex, deEndIndex, series.data, cloneData),
})
@@ -731,10 +731,13 @@ export default {
}
}
// calculate x y min and max
const xValueArray = trimValueArray(dataX, this.scaleXSelect.description)
const yValueArray = trimValueArray(dataY, this.scaleYSelect.description)
// [region] convert scale to linear or log, and calculate min and max
const xValueArray = convertValueArrayScale(dataX, this.scaleXSelect.description)
const yValueArray = convertValueArrayScale(dataY, this.scaleYSelect.description)
for (let j = 0; j < this.chartDetailData.series[0].data.length; j++) {
this.chartDetailData.series[0].data[j][0] = xValueArray[j]
this.chartDetailData.series[0].data[j][1] = yValueArray[j]
}
let targetGridRanges = this.valueRanges.find(x => x.id === channelX)
let value = getValueArrayMinAndMax(xValueArray, 'x', targetGridRanges)
this.chartDetailData.xAxis[gridIndex].min = value.min
@@ -746,6 +749,7 @@ export default {
this.chartDetailData.yAxis[gridIndex].max = value.max
// this.chartDetailData.yAxis[gridIndex].interval = (max - min) / 2
}
// [Endregion]
this.hideChartLoading()
},
async reDraw () {
@@ -862,7 +866,7 @@ export default {
this.isInitDone = true
},
beforeDestroy () {
this.$refs.chart_detail.$children[0].$children[0].clear()
this.$refs.chart_detail.clear()
for (const id in this.chartData) {
for (const _series of this.chartData[id].series) {
_series.length = 0
@@ -879,6 +883,14 @@ export default {
</script>
<style lang="scss">
.va-card__body {
padding: 0.25rem;
}
.layout.gutter--xl {
padding: 0.5rem;
}
.area-style {
height: auto;
overflow-y: hidden;
@@ -890,4 +902,18 @@ export default {
overflow-x: hidden;
}
}
.block {
display: inline-block;
margin-top: -20px;
margin-right: 10px;
height: 50px;
}
.selected_block {
display: inline-block;
margin-right: 10px;
height: 30px;
vertical-align: top;
}
</style>
@@ -1,11 +1,11 @@
<template>
<div class="flex" :class="cardclass">
<va-card>
<div>
<template slot="header">
<!-- <va-icon name="fa fa-area-chart mr-3" color="primary"/> -->
</template>
<chart :ref="'chart_ref'" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" :options="data" @dataZoom="updateZoom" :auto-resize="true"></chart>
</va-card>
</div>
</div>
</template>
@@ -57,6 +57,18 @@ export default {
updateZoom: function (e) {
this.$emit('dataZoomEvent', e)
},
showLoading: function (loadStyle) {
this.$refs.chart_ref.showLoading(loadStyle)
},
hideLoading: function () {
this.$refs.chart_ref.hideLoading()
},
appendData: function (data) {
this.$refs.chart_ref.appendData(data)
},
clear: function (data) {
this.$refs.chart_ref.clear()
},
},
async mounted () {
this.resizeTimer = setInterval(this.resize, 1000)
@@ -1,41 +1,26 @@
<template>
<div class="devices-overview">
<div>
<div>
<va-item>
<va-item-section style='text-align: center;'>
<p> Filename: </p>
<p> {{ filename }} </p>
</va-item-section>
<va-item-section style='text-align: center;'>
<va-card>
<div>
<div class="block">
<va-button flat small color="gray" icon="fa fa-file-text-o" @click.stop="editFileConfirm()"> {{ filename }} </va-button>
<va-button flat small color="gray" icon="fa fa-download" @click.stop="downloadCSV()"/>
<va-button flat small color="gray" icon="fa fa-pencil" @click.stop="editFileConfirm()"/>
<va-button flat small color="gray" icon="fa fa-trash" @click.stop="deleteFileConfirm()"/>
</va-item-section>
<va-item-section style='text-align: center;'>
<p> Current resample: </p>
<p> {{ currentScale }} to 1 </p>
</va-item-section>
<!-- <va-item-section style='float: left;'>
X axis unit
<va-select
:label="''"
v-model="valueFormatX"
textBy="unit"
:options="valueFormatOptions[channelXSelect.id]"
/>
</va-item-section> -->
<va-item-section style='float: left;'>
Y axis unit
</div>
<span class="block"> Resample: {{ currentScale }} to 1 </span>
<span class="block"> Y axis unit </span>
<div class="selected_block">
<va-select
:label="''"
v-model="valueFormatY"
textBy="unit"
:options="valueFormatOptions[channelYSelect.id]"
:noClear="true"
/>
</va-item-section>
<va-item-section style='float: left;'>
Hide grids
</div>
<span class="block"> Hide grids </span>
<div class="selected_block">
<va-select
:label="''"
v-model="ignoreGridIndexes"
@@ -43,40 +28,36 @@
:options="allChannelIndexes"
multiple
/>
</va-item-section>
</va-item>
</div>
<neulive-replay-chart :ref="'chart_overview'" class="mb-0" :key="overviewChartKey" :cardheight="'5vh'" :data="chartOverviewData"/>
<neulive-replay-chart :ref="'chart_detail'" @dblclick.native="distribute()" :cardheight="'82vh'" :data="chartDetailData" @dataZoomEvent="dataZoomEvent($event)"/>
<va-card :title="$t('Parameter')">
</div>
</div>
<neulive-replay-chart :ref="'chart_overview'" class="mb-0" :key="overviewChartKey" :cardheight="'5vh'" :data="chartOverviewData"/>
<neulive-replay-chart :ref="'chart_detail'" @dblclick.native="distribute()" :cardheight="'70vh'" :data="chartDetailData" @dataZoomEvent="dataZoomEvent($event)"/>
Parameter
<va-tree-root>
<va-tree-category label="AxisValueRangeSetting">
<div>
<div v-for="(range, index) in valueRanges" :key="index" style='width: 20%; float: left;'>
<va-item v-show="range.showXMin||range.showXMax||range.showYMin||range.showYMax">
<va-item-section align="right">
{{ range.name }}
</va-item-section>
<va-item-section>
<va-input
v-model="range.yMin"
v-show="range.showYMin"
:label="$t('yMin')"
@keyup.enter="currentAxisValueRangeChange(index, range)"
/>
</va-item-section>
<va-item-section>
<va-input
v-model="range.yMax"
v-show="range.showYMax"
:label="$t('yMax')"
@keyup.enter="currentAxisValueRangeChange(index, range)"
/>
</va-item-section>
</va-item>
</div>
<div v-for="(range, index) in valueRanges" :key="index" style='width: 20%;'>
<va-item v-show="range.showXMin||range.showXMax||range.showYMin||range.showYMax">
<va-item-section align="left">
{{ range.name }}
</va-item-section>
<va-item-section>
<va-input
v-model="range.yMin"
v-show="range.showYMin"
:label="$t('yMin')"
@keyup.enter="currentAxisValueRangeChange(index, range)"
/>
</va-item-section>
<va-item-section>
<va-input
v-model="range.yMax"
v-show="range.showYMax"
:label="$t('yMax')"
@keyup.enter="currentAxisValueRangeChange(index, range)"
/>
</va-item-section>
</va-item>
</div>
<br/>
</va-tree-category>
<va-tree-category label="Recording">
<va-tree-node>
@@ -142,6 +123,7 @@ import { exportData } from '@/data/export/export'
import types from '@/store/modules/analysis/replay/neulive/types'
import { mapFields } from 'vuex-map-fields'
import { debounce } from 'lodash'
import { file } from '@/data/file/File'
export default {
name: 'neulive-data-replay',
@@ -183,6 +165,7 @@ export default {
},
data () {
return {
fileLists: [],
isInitDone: false,
isDistributeMode: false,
metaList: null,
@@ -215,12 +198,21 @@ export default {
const rawData = await download.getAllRawDatas(meta)
exportData.exportCSV(meta, rawData)
},
async updateFileLists () {
file.clearFileList()
const files = await api.getFolderMetaFileByParent('folder', this.metaList[0].parent.folder[0])
file.updateFileList(files)
this.fileLists = file.getFileList()
},
editFileConfirm: function () {
this.updateFileLists()
this.showModal.editFile = true
},
editFile: async function () {
await api.updateMetaFile(this.editInfo.info.id, { name: this.editInfo.changedName })
await this.updateDisplaySettingRec({ updateObject: { editInfo: { name: this.editInfo.changedName }, filename: this.editInfo.changedName } })
if (this.editInfo.success === true) {
await api.updateMetaFile(this.editInfo.info.id, { name: this.editInfo.changedName })
await this.updateDisplaySettingRec({ updateObject: { editInfo: { name: this.editInfo.changedName }, filename: this.editInfo.changedName } })
}
},
undoEdit: async function () {
await this.updateDisplaySettingRec({ updateObject: { editInfo: { success: false, error: false, changedName: '', name: '', path: '' } } })
@@ -239,6 +231,18 @@ export default {
this.editInfo.success = false
this.editInfo.errorMessages.pop()
this.editInfo.errorMessages.push(this.editInfo.errorMessagesAll[0] + ' ' + illegalChar[0])
} else {
const existedFile = this.fileLists.filter(file => file.name.replace('/', '') === term)
if (existedFile.length === 0) {
this.editInfo.error = false
this.editInfo.success = true
} else {
// file name exist
this.editInfo.error = true
this.editInfo.success = false
this.editInfo.errorMessages.pop()
this.editInfo.errorMessages.push(this.editInfo.errorMessagesAll[2])
}
}
this.editInfo.changedName = term
}, 200),
@@ -311,20 +315,20 @@ export default {
}
switch (chart) {
case 'overview':
this.$refs.chart_overview.$children[0].$children[0].showLoading(loadStyle)
this.$refs.chart_overview.showLoading(loadStyle)
break
case 'detail':
this.$refs.chart_detail.$children[0].$children[0].showLoading(loadStyle)
this.$refs.chart_detail.showLoading(loadStyle)
break
default:
this.$refs.chart_overview.$children[0].$children[0].showLoading(loadStyle)
this.$refs.chart_detail.$children[0].$children[0].showLoading(loadStyle)
this.$refs.chart_overview.showLoading(loadStyle)
this.$refs.chart_detail.showLoading(loadStyle)
break
}
},
hideChartLoading: function () {
this.$refs.chart_overview.$children[0].$children[0].hideLoading()
this.$refs.chart_detail.$children[0].$children[0].hideLoading()
this.$refs.chart_overview.hideLoading()
this.$refs.chart_detail.hideLoading()
},
getData: async function (scale, sampleMethod, id, channel, meta) {
if (scale === 1) {
@@ -435,7 +439,7 @@ export default {
// silent: true,
itemStyle: {
color: '#ccc',
opacity: 0.1,
opacity: 1,
},
data: [
[{
@@ -605,7 +609,7 @@ export default {
return data
}
// getNewDataList(series.data)
this.$refs.chart_overview.$children[0].$children[0].appendData({
this.$refs.chart_overview.appendData({
seriesIndex: index,
data: getNewDataList(deStartIndex, deEndIndex, series.data, data),
})
@@ -614,7 +618,7 @@ export default {
// silent: true,
itemStyle: {
color: '#ccc',
opacity: 0.1,
opacity: 1,
},
data: [
[{
@@ -650,7 +654,7 @@ export default {
})
return data
}
this.$refs.chart_detail.$children[0].$children[0].appendData({
this.$refs.chart_detail.$children[0].appendData({
seriesIndex: index,
data: getNewDataList(deStartIndex, deEndIndex, series.data, data),
})
@@ -677,43 +681,43 @@ export default {
}
// [Region]: set chart y axis min and max
// if (!this.isDistributeMode) {
// for (let i = 0; i < dataList.length; i++) {
// if ((this.startTimeCurrent >= dataList[i].start_time && this.startTimeCurrent <= dataList[i].end_time) ||
// (this.endTimeCurrent >= dataList[i].start_time && this.endTimeCurrent <= dataList[i].end_time)) {
// const data = JSON.parse(JSON.stringify(dataList[i].data))
// const xValueArray = []
// const yValueArray = []
// for (let j = 0; j < data.length; j++) {
// xValueArray.push(data[j][0]) // time
// yValueArray.push(data[j][1])
// }
// // destructuring assignment, ref: https://medium.com/@vladbezden/how-to-get-min-or-max-of-an-array-in-javascript-1c264ec6e1aa
// let max = Math.max(...xValueArray)
// let min = Math.min(...xValueArray)
// const targetGridRanges = this.valueRanges.find(x => x.id === parseInt(ch))
// if (targetGridRanges.xMin !== '') {
// min = parseInt(targetGridRanges.xMin)
// }
// this.chartDetailData.xAxis[gridIndex].min = min
// if (targetGridRanges.xMax !== '') {
// max = parseInt(targetGridRanges.xMax)
// }
// this.chartDetailData.xAxis[gridIndex].max = max
// max = Math.max(...yValueArray)
// min = Math.min(...yValueArray)
// if (targetGridRanges.yMin !== '') {
// min = parseInt(targetGridRanges.yMin)
// }
// this.chartDetailData.yAxis[gridIndex].min = min
// if (targetGridRanges.yMax !== '') {
// max = parseInt(targetGridRanges.yMax)
// }
// this.chartDetailData.yAxis[gridIndex].max = max
// this.chartDetailData.yAxis[gridIndex].interval = (max - min) / 2
// }
// }
// }
if (!this.isDistributeMode) {
for (let i = 0; i < dataList.length; i++) {
if ((this.startTimeCurrent >= dataList[i].start_time && this.startTimeCurrent <= dataList[i].end_time) ||
(this.endTimeCurrent >= dataList[i].start_time && this.endTimeCurrent <= dataList[i].end_time)) {
const data = JSON.parse(JSON.stringify(dataList[i].data))
const xValueArray = []
const yValueArray = []
for (let j = 0; j < data.length; j++) {
xValueArray.push(data[j][0]) // time
yValueArray.push(data[j][1])
}
// destructuring assignment, ref: https://medium.com/@vladbezden/how-to-get-min-or-max-of-an-array-in-javascript-1c264ec6e1aa
let max = Math.max(...xValueArray)
let min = Math.min(...xValueArray)
const targetGridRanges = this.valueRanges.find(x => x.id === parseInt(ch))
if (targetGridRanges.xMin !== '') {
min = parseInt(targetGridRanges.xMin)
}
this.chartDetailData.xAxis[gridIndex].min = min
if (targetGridRanges.xMax !== '') {
max = parseInt(targetGridRanges.xMax)
}
this.chartDetailData.xAxis[gridIndex].max = max
max = Math.max(...yValueArray)
min = Math.min(...yValueArray)
if (targetGridRanges.yMin !== '') {
min = parseInt(targetGridRanges.yMin)
}
this.chartDetailData.yAxis[gridIndex].min = min
if (targetGridRanges.yMax !== '') {
max = parseInt(targetGridRanges.yMax)
}
this.chartDetailData.yAxis[gridIndex].max = max
this.chartDetailData.yAxis[gridIndex].interval = (max - min) / 2
}
}
}
}
// else: max min will compute in distribute function
// [EndRegion]
@@ -823,7 +827,7 @@ export default {
...mapActions('neuliveReplay', [types.meta.init]),
...mapActions('neuliveReplay', [types.rec.init, types.rec.intoData, types.rec.initDisplaySetting, types.rec.updateDisplaySetting]),
...mapMutations('neuliveReplay', [types.meta.updateByIndex]),
...mapMutations('neuliveReplay', [types.meta.updateByIndex, types.rec.initParameterSetting]),
...mapGetters('neuliveReplay', [types.meta.getAll]),
...mapGetters('neuliveReplay', [types.rec.getAll, types.rec.getAllDisplaySetting, types.rec.getDisplaySettingByKey]),
@@ -850,19 +854,22 @@ export default {
await this.initMeta({ metaIDList: metaIDList, api: api })
this.metaList = this.getAllMeta()
const meta = this.metaList[0] // [todo] 0
// console.log(meta)
await this.initParameterSetting()
await this.initDisplaySettingRec({ meta: meta })
await this.initRec({ api: api })
this.dataInfo = this.getAllRec()
await this.register()
this.drawData()
this.updateFileLists()
this.dataZoomTimer = setInterval(this.checkDataZoom, 1000)
this.allChannels = Object.keys(meta.mini_data)
this.allChannelIndexes = Array.from({ length: this.allChannels.length }, (v, i) => i.toString()) // gives [0, 1, ... , length-1]
this.isInitDone = true
},
beforeDestroy () {
this.$refs.chart_overview.$children[0].$children[0].clear()
this.$refs.chart_detail.$children[0].$children[0].clear()
this.$refs.chart_overview.clear()
this.$refs.chart_detail.clear()
for (const id in this.chartData) {
for (const _series of this.chartData[id].series) {
_series.length = 0
@@ -878,6 +885,10 @@ export default {
</script>
<style lang="scss">
.layout.gutter--xl {
padding: 0.5rem;
}
.area-style {
height: auto;
overflow-y: hidden;
@@ -889,4 +900,18 @@ export default {
overflow-x: hidden;
}
}
.block {
display: inline-block;
margin-top: -20px;
margin-right: 10px;
height: 50px;
}
.selected_block {
display: inline-block;
margin-right: 10px;
height: 30px;
vertical-align: top;
}
</style>
@@ -1,8 +1,8 @@
<template>
<div class="flex" :class="cardclass">
<va-card :style="'height: ' + cardheight + ';'">
<div>
<chart :ref="'chart_ref'" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" :options="data" @dataZoom="updateZoom" :auto-resize="true"></chart>
</va-card>
</div>
</div>
</template>
@@ -54,6 +54,18 @@ export default {
updateZoom: function (e) {
this.$emit('dataZoomEvent', e)
},
showLoading: function (loadStyle) {
this.$refs.chart_ref.showLoading(loadStyle)
},
hideLoading: function () {
this.$refs.chart_ref.hideLoading()
},
appendData: function (data) {
this.$refs.chart_ref.appendData(data)
},
clear: function (data) {
this.$refs.chart_ref.clear()
},
},
async mounted () {
this.resizeTimer = setInterval(this.resize, 1000)
@@ -68,7 +80,8 @@ export default {
<style lang='scss'>
.va-card {
&__body {
padding-top: 0.25rem;
padding-top: 0.1rem;
padding-bottom: 0.1rem;
}
}
</style>
+6 -4
View File
@@ -464,11 +464,13 @@ export default {
},
editFile: async function () {
// TODO editFile
if (this.editInfo.type !== 'folder') {
await api.updateMetaFile(this.editInfo.info.id, { name: this.editInfo.changedName })
} else {
if (this.editInfo.success === true) {
if (this.editInfo.type !== 'folder') {
await api.updateMetaFile(this.editInfo.info.id, { name: this.editInfo.changedName })
} else {
}
await this.editFileDone()
}
await this.editFileDone()
},
checkFileNameValidate: debounce(function (term) {
const illegalChar = term.match(/[^(\w\-)]+/gm)
@@ -78,11 +78,15 @@ export default {
if (this.deviceInfo.info.isSync === false) {
let fileNameCount = await api.getMetaFilesByName(name)
if (fileNameCount.data != null) {
let duplicateCount = 1
let fileName = name
while (fileNameCount.data.length !== 0) {
name += '(1)'
fileNameCount = await api.getMetaFilesByName(name)
const res = name.split('(')[0]
fileName = `${res}(${duplicateCount})`
fileNameCount = await api.getMetaFilesByName(fileName)
duplicateCount += 1
}
this.fileNameInput = name
this.fileNameInput = fileName
}
if (name !== this.deviceInfo.info.recording_file_name) {
@@ -171,11 +171,20 @@
<script>
import { taskInfo } from '../../../../data/task/TaskInfo'
import { mapFields } from 'vuex-map-fields'
import { mapMutations } from 'vuex'
import types from '@/store/modules/analysis/replay/neulive/types'
export default {
name: 'NeuliveParameterRecording',
components: {
},
computed: {
...mapFields('neuliveReplay', [
'parameterSettingInfo.ampGainOptions',
'parameterSettingInfo.sampleRateOptions',
]),
},
props: {
deviceID: {
type: Number,
@@ -190,57 +199,7 @@ export default {
return {
channelList: [],
ampGainSelect: null,
ampGainOptions: [
{
id: 0,
description: '25',
},
{
id: 1,
description: '100',
},
{
id: 2,
description: '400',
},
{
id: 3,
description: '800',
},
],
sampleRateSelect: null,
sampleRateOptions: [
{
id: 0,
value: 800,
description: '1k',
},
{
id: 1,
value: 400,
description: '2k',
},
{
id: 2,
value: 200,
description: '4k',
},
{
id: 3,
value: 160,
description: '5k',
},
{
id: 4,
value: 100,
description: '8k',
},
{
id: 5,
value: 80,
description: '10k',
},
],
// sampleRateInput: '1000',
// sampleRate: null,
recordOn: false,
@@ -293,6 +252,8 @@ export default {
}
}
const channelValue = parseInt(channelSet, 2)
// for example, if select channel 1, 2, 4, 5, and we have total 16 channel
// so we can get 0000000000011011 = 27
if (channelValue !== taskInfo.getDeviceInfo(this.deviceID).RECORDING_CH) {
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
@@ -450,8 +411,10 @@ export default {
},
)
},
...mapMutations('neuliveReplay', [types.rec.initParameterSetting]),
},
mounted () {
async mounted () {
await this.initParameterSetting()
this.refresh()
},
destroyed () {
@@ -28,6 +28,7 @@
<div class="mt-4">
<div class="row sm12 xl12 md12 xs12">
<p class="display-6">ELECTRODE</p>
<va-button flat color="gray" icon="fa fa-info-circle" style="margin: 0.001rem; padding: 0.001rem;" @click.stop="toggleModal('ELECTRODE')"/>
</div>
<div class="row">
<div class="flex sm12 xl12 md12 xs12">
@@ -174,6 +175,7 @@
<div class="mt-4">
<div class="row sm12 xl12 md12 xs12">
<p class="display-6">PATTERN</p>
<va-button flat color="gray" icon="fa fa-info-circle" style="margin: 0.001rem; padding: 0.001rem;" @click.stop="toggleModal('PATTERN')"/>
</div>
<div class="row">
<div class="flex sm12 xl12 md12 xs12">
@@ -183,7 +185,10 @@
outline
v-model="patternModeSelect"
:options="patternModeOptions"
/>
>
</va-button-toggle>
<img src='@/assets/img/Monophasic.png' v-if="patternModeSelect==0" class="sti_pattern_img">
<img src='@/assets/img/Biphasic.png' v-if="patternModeSelect==1" class="sti_pattern_img">
</div>
</div>
@@ -326,13 +331,28 @@
</div>
</div>
</div>
<va-modal
v-model="showGuideLineModal.ELECTRODE"
position="right"
>
<img src='@/assets/img/sti_user_guide.png' class="sti_guideline">
</va-modal>
<va-modal
v-model="showGuideLineModal.PATTERN"
position="right"
>
<img src='@/assets/img/sti_user_guide.png' class="sti_guideline">
</va-modal>
</div>
</template>
<script>
import { taskInfo } from '../../../../data/task/TaskInfo'
import { mapFields } from 'vuex-map-fields'
import { mapMutations } from 'vuex'
import types from '@/store/modules/analysis/replay/neulive/types'
export default {
name: 'NeuliveParameterStimulation',
@@ -350,62 +370,19 @@ export default {
},
data () {
return {
showGuideLineModal: { ELECTRODE: false, PATTERN: false },
stimulationOn: false,
posChannelList: [2],
negChannelList: [1],
stimulateElectrodeSelect: null,
stimulateElectrodeOptions: [
{
label: 'Monopolar',
value: 0,
},
{
label: 'Bipolar',
value: 1,
},
],
cycleNumberSelect: null,
cycleNumberOptions: [
{
label: 'limite',
value: 0,
},
{
label: 'Unlimite',
value: 1,
},
],
cycleNumberInput: '1',
cycleNumber: 1,
cycleNumberArray: Array(9).fill(1),
amplitudeNumberInput: '50',
amplitudeNumber: 50,
patternModeSelect: null,
patternModeOptions: [
{
label: 'Monophasic',
value: 0,
},
{
label: 'Biphasic',
value: 1,
},
],
unitSelect: 1,
unitOptions: [
{
label: 's',
value: 0,
},
{
label: 'ms',
value: 1,
},
{
label: 'us',
value: 2,
},
],
unitMultiply: 1000,
// period = (t1 + t2 + t3 + t4) * 10
frequencyNumberInput: '0',
@@ -436,10 +413,24 @@ export default {
return true
}
},
...mapFields('neuliveReplay', [
'parameterSettingInfo.stimulateElectrodeOptions',
'parameterSettingInfo.cycleNumberOptions',
'parameterSettingInfo.patternModeOptions',
'parameterSettingInfo.unitOptions',
]),
},
mqtt: {
},
methods: {
toggleModal (which) {
if (which === 'ELECTRODE') {
this.showGuideLineModal.ELECTRODE = true
} else if (which === 'PATTERN') {
this.showGuideLineModal.PATTERN = true
}
},
mqttPub: function (topic, mes) {
this.$mqtt.publish(topic, mes)
},
@@ -813,11 +804,31 @@ export default {
}))
}
},
...mapMutations('neuliveReplay', [types.rec.initParameterSetting]),
},
mounted () {
async mounted () {
await this.initParameterSetting()
this.refresh()
},
watch: {
},
}
</script>
<style lang="scss">
.sti_guideline {
height: 75vh;
width: 65vw;
text-align: left;
justify-content: center;
position: relative;
}
.sti_pattern_img {
height: 22.5vh;
width: 17.5vw;
text-align: center;
justify-content: center;
position: relative;
}
</style>
+1 -1
View File
@@ -17,7 +17,7 @@ export function getCurrentTimestamp () {
return timestamp
}
export function trimValueArray (data, mode) {
export function convertValueArrayScale (data, mode) {
const valueArray = []
for (let j = 0; j < data.length; j++) {
let tmp = data[j][1]
@@ -18,6 +18,7 @@ function makeXAxis (gridIndex, type) {
scale: true,
min: null,
max: null,
splitNumber: 10,
}
}
@@ -37,6 +37,111 @@ const recMutations = {
state.recInfo[payload.metaID][payload.channel][payload.scale][payload.index].load = true
},
/*
* init parameter setting
*/
[typePath.initParameterSetting]: function (state, payload) {
state.parameterSettingInfo.ampGainOptions = [
{
id: 0,
description: '25',
},
{
id: 1,
description: '100',
},
{
id: 2,
description: '400',
},
{
id: 3,
description: '800',
},
]
state.parameterSettingInfo.sampleRateOptions = [
{
id: 0,
value: 800,
description: '1k',
},
{
id: 1,
value: 400,
description: '2k',
},
{
id: 2,
value: 200,
description: '4k',
},
{
id: 3,
value: 160,
description: '5k',
},
{
id: 4,
value: 100,
description: '8k',
},
{
id: 5,
value: 80,
description: '10k',
},
]
state.parameterSettingInfo.stimulateElectrodeOptions = [
{
label: 'Monopolar',
value: 0,
},
{
label: 'Bipolar',
value: 1,
},
]
state.parameterSettingInfo.cycleNumberOptions = [
{
label: 'limite',
value: 0,
},
{
label: 'Unlimite',
value: 1,
},
]
state.parameterSettingInfo.patternModeOptions = [
{
label: 'Monophasic',
value: 0,
},
{
label: 'Biphasic',
value: 1,
},
]
state.parameterSettingInfo.unitOptions = [
{
label: 's',
value: 0,
},
{
label: 'ms',
value: 1,
},
{
label: 'us',
value: 2,
},
]
},
/**
* init rec display setting
*
@@ -102,18 +207,137 @@ const recMutations = {
state.displaySettingInfo.parameterInfo = { recording: '', stimulation: '' }
state.displaySettingInfo.parameterInfo.recording += 'Duration: ' + parseInt(parseInt(payload.meta.time_duration / 1000000) / 60) + ' m ' + parseInt((payload.meta.time_duration % 60000000) / 1000000) + ' s<br/>'
state.displaySettingInfo.parameterInfo.recording += '<br/>Parameter: <br/>'
for (const [key, value] of Object.entries(params)) {
if (!(key.includes('sti') || key.includes('STI'))) {
state.displaySettingInfo.parameterInfo.recording += ' ' + key + ': ' + value + '<br/>'
}
}
state.displaySettingInfo.parameterInfo.stimulation += 'Duration: ' + parseInt(parseInt(payload.meta.time_duration / 1000000) / 60) + ' m ' + parseInt((payload.meta.time_duration % 60000000) / 1000000) + ' s<br/>'
state.displaySettingInfo.parameterInfo.stimulation += '<br/>Parameter: <br/>'
for (const [key, value] of Object.entries(params)) {
if (key.includes('sti') || key.includes('STI')) {
state.displaySettingInfo.parameterInfo.stimulation += ' ' + key + ': ' + value + '<br/>'
if (!(key.includes('sti') || key.includes('STI'))) {
let showKey = ''
let showValue = value
if (key === 'RECORDING_CH' || key === 'AXIS_CH' || key === 'AMP_GAIN' || key === 'ADC_CLOCK') {
if (key === 'RECORDING_CH') {
showKey = 'Channels'
// convert decimal to binary
const binaryChannelValue = showValue.toString(2)
const channelValue = binaryChannelValue.split('')
showValue = ''
channelValue.forEach(function (value, i) {
if (value === '1') {
showValue += `${i + 1} `
}
})
if (showValue === '') {
showValue = 'None'
}
} else if (key === 'AXIS_CH') {
showKey = '3-AXIS'
// convert decimal to binary
const binaryChannelValue = showValue.toString(2)
const channelValue = binaryChannelValue.split('').reverse()
showValue = ''
channelValue.forEach(function (value, i) {
if (value === '1') {
if (i === 0) {
showValue += 'x '
} else if (i === 1) {
showValue += 'y '
} else if (i === 2) {
showValue += 'z '
} else if (i === 3) {
showValue += 'mag '
}
}
})
if (showValue === '') {
showValue = 'None'
}
} else if (key === 'AMP_GAIN') {
showKey = 'Amp gain'
const targetID = (value + 1) % 4
for (let i = 0; i < state.parameterSettingInfo.ampGainOptions.length; i++) {
if (state.parameterSettingInfo.ampGainOptions[i].id === targetID) {
showValue = state.parameterSettingInfo.ampGainOptions[i].description
}
}
// state.parameterSettingInfo.ampGainOptions
} else if (key === 'ADC_CLOCK') {
showKey = 'Sample Rate'
for (let i = 0; i < state.parameterSettingInfo.sampleRateOptions.length; i++) {
if (state.parameterSettingInfo.sampleRateOptions[i].value === value) {
showValue = state.parameterSettingInfo.sampleRateOptions[i].description
}
}
}
state.displaySettingInfo.parameterInfo.recording += ' ' + showKey + ': ' + showValue + '<br/>'
}
} else {
// sti param
let showKey = ''
let showValue = value
if (key === 'STI_H_BRIDGE' || key === 'STI_CHANNEL' || key === 'STI_POLARITY' || key === 'CONTINUOUS_STI' ||
key === 'STI_AMPLITUDE' || key === 'STI_PATTERN' || key === 'STI_T1' || key === 'STI_T2' || key === 'STI_T3' || key === 'STI_T4') {
if (key === 'STI_H_BRIDGE') {
showKey = 'ELECTRODE'
if (value === true) {
showValue = state.parameterSettingInfo.stimulateElectrodeOptions[1].label
} else {
showValue = state.parameterSettingInfo.stimulateElectrodeOptions[0].label
}
} else if (key === 'STI_CHANNEL' || key === 'STI_POLARITY') {
if (key === 'STI_CHANNEL') {
showKey = 'Channels'
} else {
showKey = 'Polarity'
}
// convert decimal to binary
const binaryChannelValue = showValue.toString(2)
const channelValue = binaryChannelValue.split('')
showValue = ''
channelValue.forEach(function (value, i) {
if (value === '1') {
showValue += `${i + 1} `
}
})
if (showValue === '') {
showValue = 'None'
}
} else if (key === 'CONTINUOUS_STI') {
showKey = 'CYCLE NUMBER'
if (value === true) {
showValue = state.parameterSettingInfo.cycleNumberOptions[1].label
} else {
showValue = state.parameterSettingInfo.cycleNumberOptions[0].label
}
} else if (key === 'STI_AMPLITUDE') {
showKey = 'AMPLITUDE (uA)'
showValue = value * 5
} else if (key === 'STI_PATTERN') {
showKey = 'PATTERN'
if (value === true) {
showValue = state.parameterSettingInfo.patternModeOptions[1].label
} else {
showValue = state.parameterSettingInfo.patternModeOptions[0].label
}
} else if (key === 'STI_T1') {
showKey = 'T1 Range'
showValue = `${value[0] * 10 / 1000} ms` // 10 is cuz 1 value = 10us, [0] is cuz now all values in array are same
} else if (key === 'STI_T2') {
showKey = 'T2 Range'
showValue = `${value[0] * 10 / 1000} ms` // 10 is cuz 1 value = 10us
} else if (key === 'STI_T3') {
showKey = 'T3 Range'
showValue = `${value[0] * 10 / 1000} ms` // 10 is cuz 1 value = 10us
} else if (key === 'STI_T4') {
showKey = 'T4 Range'
showValue = `${value[0] * 10 / 1000} ms` // 10 is cuz 1 value = 10us
}
state.displaySettingInfo.parameterInfo.stimulation += ' ' + showKey + ': ' + showValue + '<br/>'
}
}
}
const period = (params.STI_T1[0] + params.STI_T2[0] + params.STI_T3[0] + params.STI_T4[0]) * 10 / 1000 // 10 is cuz 1 value = 10us
state.displaySettingInfo.parameterInfo.stimulation += ' Frequency: ' + String(1000 / period) + ' Hz' + '<br/>' // 1000 is cuz 1s = 1000ms
state.displaySettingInfo.parameterInfo.stimulation += ' Period: ' + String(period) + ' ms' + '<br/>'
state.displaySettingInfo.editInfo = {
info: { id: payload.meta.id },
@@ -14,6 +14,14 @@ function newState () {
// ]
// }
metaList: [],
parameterSettingInfo: {
ampGainOptions: [],
sampleRateOptions: [],
stimulateElectrodeOptions: [],
cycleNumberOptions: [],
patternModeOptions: [],
unitOptions: [],
},
displaySettingInfo: {
valueRanges: [], // each element: { id: ID, name: channelName, xMin: 0, xMax: 0, yMin: 0, yMax: 0 }
valueFormatOptions: {},
@@ -46,6 +46,7 @@ const types = {
init: 'initRec',
intoData: 'intoDataRec',
initDisplaySetting: 'initDisplaySettingRec',
initParameterSetting: 'initParameterSetting',
set: 'setRec',
update: 'updateRec',