Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MindSpore
mindinsight
提交
5c27dcc9
M
mindinsight
项目概览
MindSpore
/
mindinsight
通知
7
Star
3
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
M
mindinsight
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
5c27dcc9
编写于
4月 18, 2020
作者:
P
ph
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add histogram
上级
ecab5e89
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
1725 addition
and
15 deletion
+1725
-15
mindinsight/ui/src/assets/images/comming-soon.png
mindinsight/ui/src/assets/images/comming-soon.png
+0
-0
mindinsight/ui/src/components/multiselectGroup.vue
mindinsight/ui/src/components/multiselectGroup.vue
+0
-0
mindinsight/ui/src/views/train-manage/histogram.vue
mindinsight/ui/src/views/train-manage/histogram.vue
+1418
-0
mindinsight/ui/src/views/train-manage/image.vue
mindinsight/ui/src/views/train-manage/image.vue
+6
-6
mindinsight/ui/src/views/train-manage/training-dashboard.vue
mindinsight/ui/src/views/train-manage/training-dashboard.vue
+301
-9
未找到文件。
mindinsight/ui/src/assets/images/comming-soon.png
0 → 100644
浏览文件 @
5c27dcc9
5.8 KB
mindinsight/ui/src/components/
checkList
.vue
→
mindinsight/ui/src/components/
multiselectGroup
.vue
浏览文件 @
5c27dcc9
文件已移动
mindinsight/ui/src/views/train-manage/histogram.vue
0 → 100644
浏览文件 @
5c27dcc9
<!--
Copyright 2020 Huawei Technologies Co., Ltd.All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<
template
>
<div
class=
"cl-histogram-manage"
>
<div
class=
"histogram-bk"
>
<!-- Title area -->
<div
class=
"cl-title cl-histogram-title"
>
<div
class=
"cl-title-left"
>
{{
$t
(
'
histogram.titleText
'
)
}}
</div>
<div
class=
"cl-title-right"
>
<div
class=
"cl-close-btn"
@
click=
"jumpToTrainDashboard"
>
<img
src=
"@/assets/images/close-page.png"
/>
</div>
</div>
</div>
<!-- List item operation area -->
<div
class=
"cl-histogram-operate-content"
>
<multiselectGroupComponents
ref=
"multiselectGroupComponents"
:checkListArr=
"tagList"
@
selectedChange=
"tagSelectedChanged"
></multiselectGroupComponents>
</div>
<!-- Area for selecting a view type -->
<div
class=
"cl-histogram-view-type-select-content"
>
<div
class=
"view-title"
>
{{
$t
(
'
histogram.xAxisTitle
'
)
}}
</div>
<el-radio-group
v-model=
"curAxisName"
fill=
"#00A5A7"
text-color=
"#FFFFFF"
size=
"small"
:disabled=
"curViewName === 0"
@
change=
"timeTypeChange"
>
<el-radio-button
:label=
0
>
{{
$t
(
'
histogram.step
'
)
}}
</el-radio-button>
<el-radio-button
:label=
1
>
{{
$t
(
'
histogram.relativeTime
'
)
}}
</el-radio-button>
<el-radio-button
:label=
2
>
{{
$t
(
'
histogram.absoluteTime
'
)
}}
</el-radio-button>
</el-radio-group>
<div
class=
"view-title"
>
{{
$t
(
'
histogram.viewType
'
)
}}
</div>
<el-radio-group
v-model=
"curViewName"
fill=
"#00A5A7"
text-color=
"#FFFFFF"
size=
"small"
@
change=
"viewTypeChange"
>
<el-radio-button
:label=
0
>
{{
$t
(
'
histogram.overlay
'
)
}}
</el-radio-button>
<el-radio-button
:label=
1
>
{{
$t
(
'
histogram.offset
'
)
}}
</el-radio-button>
</el-radio-group>
</div>
<!-- Content display area -->
<div
class=
"cl-histogram-show-data-content"
>
<!-- No data -->
<div
class=
"image-noData"
v-if=
"initOver && !originDataArr.length"
>
<div>
<img
:src=
"require('@/assets/images/nodata.png')"
/>
</div>
<div
class=
"noData-text"
>
{{
$t
(
'
public.noData
'
)
}}
</div>
</div>
<!-- Data -->
<div
class=
"data-content"
v-if=
"!!originDataArr.length"
>
<div
id=
"echartTip"
v-show=
"chartTipFlag"
>
<table
class=
"char-tip-table borderspacing3"
>
<tr>
<td>
{{
$t
(
'
histogram.centerValue
'
)
}}
</td>
<td>
{{
$t
(
'
histogram.step
'
)
}}
</td>
<td>
{{
$t
(
'
histogram.relativeTime
'
)
}}
</td>
<td>
{{
$t
(
'
histogram.absoluteTime
'
)
}}
</td>
</tr>
<tr
id=
"tipTr"
></tr>
</table>
</div>
<div
class=
"sample-content"
v-for=
"sampleItem in originDataArr"
:key=
"sampleItem.domId"
:class=
"sampleItem.fullScreen?'char-full-screen':''"
v-show=
"sampleItem.show"
>
<div
class=
"chars-container"
>
<div
class=
"char-item-content"
:id=
"sampleItem.domId"
></div>
</div>
</div>
</div>
</div>
<!-- Page number area -->
<div
class=
"pagination-content"
v-if=
"originDataArr.length"
>
<el-pagination
@
current-change=
"currentPageChange"
:current-page=
"pageIndex + 1"
:page-sizes=
"pageSizes"
:page-size=
"pageNum"
layout=
"total, prev, pager, next, jumper"
:total=
"curFilterSamples.length"
>
</el-pagination>
</div>
</div>
</div>
</
template
>
<
script
>
import
multiselectGroupComponents
from
'
../../components/multiselectGroup.vue
'
;
import
RequestService
from
'
../../services/request-service
'
;
import
CommonProperty
from
'
../../common/common-property
'
;
import
echarts
from
'
echarts
'
;
import
{
format
,
precisionRound
}
from
'
d3
'
;
const
d3
=
{
format
,
precisionRound
};
export
default
{
data
()
{
return
{
tagList
:
[],
// Tag list.
trainingJobId
:
this
.
$route
.
query
.
train_id
,
// ID of the current training job.
originDataArr
:
[],
// List of all data.
initOver
:
false
,
// Indicates whether the initialization is complete.
curAxisName
:
0
,
// Current time type.
curViewName
:
1
,
// Current view type.
curFullTagDic
:
{},
// Dictionary that contains all the current tags.
multiSelectedTagNames
:
{},
// Dictionary for storing the name of the selected tags.
curFilterSamples
:
[],
// List of data that meet the current filter criteria.
curPageArr
:
[],
// Data list on the current page.
pageIndex
:
0
,
// Current page number.
pageSizes
:
[
6
],
// The number of records on each page is optional.
pageNum
:
6
,
// Number of records on each page.
isReloading
:
false
,
// Manually refresh.
autoUpdateTimer
:
null
,
// Automatic refresh timer.
zrDrawElement
:
{
hoverDots
:
[]},
chartTipFlag
:
false
,
charResizeTimer
:
null
,
};
},
computed
:
{
/**
* Global refresh switch
* @return {Boolean}
*/
isReload
()
{
return
this
.
$store
.
state
.
isReload
;
},
/**
* Automatic refresh switch
* @return {Boolean}
*/
isTimeReload
()
{
return
this
.
$store
.
state
.
isTimeReload
;
},
/**
* Automatic refresh value
* @return {Boolean}
*/
timeReloadValue
()
{
return
this
.
$store
.
state
.
timeReloadValue
;
},
},
components
:
{
multiselectGroupComponents
,
},
watch
:
{
/**
* Global refresh switch listener
* @param {Boolean} newVal Value after change
* @param {Boolean} oldVal Value before change
*/
isReload
(
newVal
,
oldVal
)
{
if
(
newVal
)
{
this
.
isReloading
=
true
;
// Automatic refresh and retiming
if
(
this
.
isTimeReload
)
{
this
.
autoUpdateSamples
();
}
this
.
updateAllData
(
false
);
}
},
/**
* Automatic refresh switch listener
* @param {Boolean} newVal Value after change
* @param {Boolean} oldVal Value before change
*/
isTimeReload
(
newVal
,
oldVal
)
{
if
(
newVal
)
{
// Enable automatic refresh
this
.
autoUpdateSamples
();
}
else
{
// Disable automatic refresh
this
.
stopUpdateSamples
();
}
},
/**
* The refresh time is changed
*/
timeReloadValue
()
{
this
.
autoUpdateSamples
();
},
},
destroyed
()
{
window
.
removeEventListener
(
'
resize
'
,
this
.
resizeCallback
);
// Disable the automatic refresh function
if
(
this
.
autoUpdateTimer
)
{
clearInterval
(
this
.
autoUpdateTimer
);
this
.
autoUpdateTimer
=
null
;
}
// Stop refreshing
if
(
this
.
isReloading
)
{
this
.
$store
.
commit
(
'
setIsReload
'
,
false
);
this
.
isReloading
=
false
;
}
},
mounted
()
{
this
.
init
();
window
.
addEventListener
(
'
resize
'
,
this
.
resizeCallback
,
false
);
},
methods
:
{
resizeCallback
()
{
if
(
this
.
charResizeTimer
)
{
clearTimeout
(
this
.
charResizeTimer
);
this
.
charResizeTimer
=
null
;
}
this
.
charResizeTimer
=
setTimeout
(()
=>
{
this
.
curPageArr
.
forEach
((
sampleItem
)
=>
{
if
(
sampleItem
.
charObj
)
{
sampleItem
.
charObj
.
resize
();
}
});
},
500
);
},
/**
* Initialize
*/
init
()
{
this
.
getOriginData
();
if
(
this
.
isTimeReload
)
{
this
.
autoUpdateSamples
();
}
},
/**
* jump back to train dashboard
*/
jumpToTrainDashboard
()
{
this
.
$router
.
push
({
path
:
'
/train-manage/training-dashboard
'
,
query
:
{
id
:
this
.
trainingJobId
,
},
});
},
/**
* Obtains original data.
*/
getOriginData
()
{
const
params
=
{
plugin_name
:
'
histogram
'
,
train_id
:
this
.
trainingJobId
,
};
RequestService
.
getSingleTrainJob
(
params
)
.
then
((
res
)
=>
{
if
(
!
res
||
!
res
.
data
||
!
res
.
data
.
train_jobs
||
!
res
.
data
.
train_jobs
.
length
)
{
this
.
initOver
=
true
;
return
;
}
const
data
=
res
.
data
.
train_jobs
[
0
];
if
(
!
data
.
tags
)
{
return
;
}
const
tagList
=
[];
const
dataList
=
[];
data
.
tags
.
forEach
((
tagName
)
=>
{
if
(
!
this
.
curFullTagDic
[
tagName
])
{
this
.
curFullTagDic
[
tagName
]
=
true
;
tagList
.
push
({
label
:
tagName
,
checked
:
true
,
show
:
true
,
});
const
sampleIndex
=
dataList
.
length
;
dataList
.
push
({
tagName
:
tagName
,
sampleIndex
:
sampleIndex
,
show
:
false
,
fullScreen
:
false
,
domId
:
`
${
tagName
}
`
,
charData
:
{
oriData
:
[],
charOption
:
{},
},
charObj
:
null
,
});
}
});
this
.
tagList
=
tagList
;
this
.
originDataArr
=
dataList
;
this
.
$nextTick
(()
=>
{
this
.
multiSelectedTagNames
=
this
.
$refs
.
multiselectGroupComponents
.
updateSelectedDic
();
this
.
initOver
=
true
;
this
.
updateTagInPage
();
});
},
this
.
requestErrorCallback
)
.
catch
((
e
)
=>
{
this
.
initOver
=
true
;
this
.
$message
.
error
(
this
.
$t
(
'
public.dataError
'
));
});
},
/**
* The selected label is changed.
* @param {Object} selectedItemDict Dictionary containing the selected tags
*/
tagSelectedChanged
(
selectedItemDict
)
{
if
(
!
selectedItemDict
)
{
return
;
}
this
.
multiSelectedTagNames
=
selectedItemDict
;
// Reset to the first page
this
.
pageIndex
=
0
;
this
.
updateTagInPage
();
},
/**
* Page number change event
* @param {Number} pageIndex Changed page number
*/
currentPageChange
(
pageIndex
)
{
this
.
pageIndex
=
pageIndex
-
1
;
// Load the data on the current page
this
.
getCurPageDataArr
();
},
/**
* Obtains data on the current page
* @param {Boolean} noPageDataNumChange No new data is added or deleted
*/
getCurPageDataArr
(
noPageDataNumChange
)
{
// Clear the previous page
if
(
!
noPageDataNumChange
)
{
this
.
curPageArr
.
forEach
((
sampleItem
)
=>
{
sampleItem
.
show
=
false
;
});
}
// This interface is used to obtain the current page group and hide the current page group.
const
startIndex
=
this
.
pageIndex
*
this
.
pageNum
;
const
endIndex
=
startIndex
+
this
.
pageNum
;
const
curPageArr
=
[];
for
(
let
i
=
startIndex
;
i
<
endIndex
;
i
++
)
{
const
sampleItem
=
this
.
curFilterSamples
[
i
];
if
(
sampleItem
)
{
sampleItem
.
show
=
true
;
curPageArr
.
push
(
sampleItem
);
}
}
this
.
curPageArr
=
curPageArr
;
// Update the data information on the current page
this
.
freshCurPageData
();
},
freshCurPageData
()
{
this
.
curPageArr
.
forEach
((
item
,
index
)
=>
{
this
.
updateCurPageSamples
(
item
.
sampleIndex
);
});
},
updateCurPageSamples
(
sampleIndex
)
{
const
item
=
this
.
originDataArr
[
sampleIndex
];
const
promiseArr
=
[];
if
(
!
item
||
!
item
.
tagName
)
{
return
;
}
const
params
=
{
train_id
:
this
.
trainingJobId
,
tag
:
item
.
tagName
,
};
promiseArr
.
push
(
this
.
addPromise
(
params
));
Promise
.
all
(
promiseArr
.
map
(
function
(
promiseItem
)
{
return
promiseItem
.
catch
(
function
(
err
)
{
return
err
;
});
}),
).
then
((
res
)
=>
{
if
(
!
res
||
!
res
.
length
||
!
res
[
0
].
data
)
{
return
;
}
const
data
=
res
[
0
].
data
;
this
.
originDataArr
[
sampleIndex
].
charData
.
oriData
=
this
.
formOriData
(
data
,
);
const
charOption
=
this
.
formatDataToChar
(
sampleIndex
);
this
.
updateSampleData
(
sampleIndex
,
charOption
);
});
},
addPromise
(
params
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
RequestService
.
getHistogramData
(
params
)
.
then
((
res
)
=>
{
if
(
res
)
{
res
.
params
=
params
;
resolve
(
res
);
}
})
.
catch
((
error
)
=>
{
if
(
error
)
{
reject
(
error
);
}
});
});
},
/**
* The time display type is changed
* @param {Number} val Current mode
*/
timeTypeChange
(
val
)
{
this
.
curPageArr
.
forEach
((
k
)
=>
{
const
charOption
=
this
.
formatDataToChar
(
k
.
sampleIndex
);
this
.
updateSampleData
(
k
.
sampleIndex
,
charOption
);
});
},
/**
* The view display type is changed
* @param {Number} val Current mode
*/
viewTypeChange
(
val
)
{
this
.
curPageArr
.
forEach
((
k
)
=>
{
const
charOption
=
this
.
formatDataToChar
(
k
.
sampleIndex
);
this
.
updateSampleData
(
k
.
sampleIndex
,
charOption
);
});
},
/**
* Update the data list based on the filtered tags
* @param {Boolean} noPageDataNumChange No new data is added or deleted
*/
updateTagInPage
(
noPageDataNumChange
)
{
const
curFilterSamples
=
[];
// Obtains data subscript that meets the tag filtering conditions
this
.
originDataArr
.
forEach
((
sampleItem
)
=>
{
if
(
this
.
multiSelectedTagNames
[
sampleItem
.
tagName
])
{
curFilterSamples
.
push
(
sampleItem
);
}
});
this
.
curFilterSamples
=
curFilterSamples
;
// Obtains data on the current page
this
.
getCurPageDataArr
(
noPageDataNumChange
);
},
/**
* Clear data
*/
clearAllData
()
{
this
.
tagList
=
[];
this
.
originDataArr
=
[];
this
.
curFullTagDic
=
{};
this
.
multiSelectedTagNames
=
{};
this
.
curFilterSamples
=
[];
this
.
pageIndex
=
0
;
this
.
curPageArr
=
[];
this
.
$nextTick
(()
=>
{
this
.
$refs
.
multiselectGroupComponents
.
updateSelectedDic
();
});
},
/**
* error
* @param {Object} error error object
*/
requestErrorCallback
(
error
)
{
if
(
!
this
.
initOver
)
{
this
.
initOver
=
true
;
}
if
(
this
.
isReloading
)
{
this
.
$store
.
commit
(
'
setIsReload
'
,
false
);
this
.
isReloading
=
false
;
}
if
(
error
.
response
&&
error
.
response
.
data
)
{
this
.
clearAllData
();
}
else
{
if
(
!
(
error
.
code
===
'
ECONNABORTED
'
&&
/^timeout/
.
test
(
error
.
message
))
)
{
// Clear data
this
.
clearAllData
();
}
}
},
/**
* Enable automatic refresh
*/
autoUpdateSamples
()
{
if
(
this
.
autoUpdateTimer
)
{
clearInterval
(
this
.
autoUpdateTimer
);
this
.
autoUpdateTimer
=
null
;
}
this
.
autoUpdateTimer
=
setInterval
(()
=>
{
this
.
$store
.
commit
(
'
clearToken
'
);
this
.
updateAllData
(
true
);
},
this
.
timeReloadValue
*
1000
);
},
/**
* Disable automatic refresh
*/
stopUpdateSamples
()
{
if
(
this
.
autoUpdateTimer
)
{
clearInterval
(
this
.
autoUpdateTimer
);
this
.
autoUpdateTimer
=
null
;
}
},
/**
* Update all data.
* @param {Boolean} ignoreError whether ignore error tip.
*/
updateAllData
(
ignoreError
)
{
const
params
=
{
plugin_name
:
'
histogram
'
,
train_id
:
this
.
trainingJobId
,
};
RequestService
.
getSingleTrainJob
(
params
,
ignoreError
)
.
then
((
res
)
=>
{
if
(
this
.
isReloading
)
{
this
.
$store
.
commit
(
'
setIsReload
'
,
false
);
this
.
isReloading
=
false
;
}
// Fault tolerance processing
if
(
!
res
||
!
res
.
data
||
!
res
.
data
.
train_jobs
||
!
res
.
data
.
train_jobs
.
length
||
!
res
.
data
.
train_jobs
[
0
].
tags
)
{
this
.
clearAllData
();
return
;
}
const
data
=
res
.
data
.
train_jobs
[
0
];
// Remove data that does not exist.
const
dataRemoveFlag
=
this
.
removeNoneExistentData
(
data
);
// Add new data.
const
dataAddFlag
=
this
.
checkNewDataAndComplete
(
data
);
this
.
$nextTick
(()
=>
{
this
.
multiSelectedTagNames
=
this
.
$refs
.
multiselectGroupComponents
.
updateSelectedDic
();
this
.
updateTagInPage
(
!
dataAddFlag
&&
!
dataRemoveFlag
);
});
},
this
.
requestErrorCallback
)
.
catch
((
e
)
=>
{
this
.
$message
.
error
(
this
.
$t
(
'
public.dataError
'
));
});
},
/**
* Delete the data that does not exist
* @param {Object} oriData Raw data with tags
* @return {Boolean} Indicates whether data is removed.
*/
removeNoneExistentData
(
oriData
)
{
if
(
!
oriData
||
!
oriData
.
tags
)
{
return
false
;
}
const
newTagDictionaries
=
{};
let
dataRemoveFlag
=
false
;
// Obtains the current tag list
oriData
.
tags
.
forEach
((
tagName
)
=>
{
newTagDictionaries
[
tagName
]
=
true
;
});
// Delete data that do not exist in the operation bar
const
oldTagListLength
=
this
.
tagList
.
length
;
for
(
let
i
=
oldTagListLength
-
1
;
i
>=
0
;
i
--
)
{
if
(
!
newTagDictionaries
[
this
.
tagList
[
i
].
label
])
{
dataRemoveFlag
=
true
;
delete
this
.
curFullTagDic
[
this
.
tagList
[
i
].
label
];
this
.
tagList
.
splice
(
i
,
1
);
}
}
// Delete the data corresponding to the tag that does not exist.
const
oldSampleLength
=
this
.
originDataArr
.
length
;
for
(
let
i
=
oldSampleLength
-
1
;
i
>=
0
;
i
--
)
{
if
(
!
newTagDictionaries
[
this
.
originDataArr
[
i
].
tagName
])
{
dataRemoveFlag
=
true
;
this
.
originDataArr
.
splice
(
i
,
1
);
}
}
this
.
originDataArr
.
forEach
((
item
,
index
)
=>
{
item
.
sampleIndex
=
index
;
});
return
dataRemoveFlag
;
},
/**
* Check and add new data
* @param {Object} oriData Raw data with tags
* @return {Boolean} Check whether new data is added
*/
checkNewDataAndComplete
(
oriData
)
{
if
(
!
oriData
||
!
oriData
.
tags
)
{
return
false
;
}
let
dataAddFlag
=
false
;
oriData
.
tags
.
forEach
((
tagName
)
=>
{
if
(
!
this
.
curFullTagDic
[
tagName
])
{
this
.
tagList
.
push
({
label
:
tagName
,
checked
:
true
,
show
:
false
,
});
const
sampleIndex
=
this
.
originDataArr
.
length
;
this
.
originDataArr
.
push
({
tagName
:
tagName
,
show
:
false
,
fullScreen
:
false
,
sampleIndex
:
sampleIndex
,
domId
:
`
${
tagName
}
`
,
charData
:
{
oriData
:
[],
charOption
:
{},
},
charObj
:
null
,
});
this
.
curFullTagDic
[
tagName
]
=
true
;
dataAddFlag
=
true
;
}
});
return
dataAddFlag
;
},
/**
* update sample data
* @param {Number} sampleIndex index
* @param {Object} charOption data
*/
updateSampleData
(
sampleIndex
,
charOption
)
{
let
curViewName
=
this
.
curViewName
;
const
sampleObject
=
this
.
originDataArr
[
sampleIndex
];
sampleObject
.
charData
=
sampleObject
.
charData
?
sampleObject
.
charData
:
{};
sampleObject
.
charData
.
charOption
=
this
.
formatCharOption
(
sampleIndex
,
charOption
,
);
if
(
!
sampleObject
.
charObj
)
{
sampleObject
.
charObj
=
echarts
.
init
(
document
.
getElementById
(
sampleObject
.
domId
),
null
,
);
}
setTimeout
(()
=>
{
sampleObject
.
charObj
.
setOption
(
sampleObject
.
charData
.
charOption
,
true
);
},
10
);
const
zr
=
sampleObject
.
charObj
.
getZr
();
const
p
=
Math
.
max
(
0
,
d3
.
precisionRound
(
0.01
,
1.01
)
-
1
);
const
yValueFormat
=
d3
.
format
(
'
.
'
+
p
+
'
e
'
);
const
chartData
=
sampleObject
.
charData
.
oriData
.
chartData
;
const
rawData
=
charOption
.
seriesData
;
/**
* get convert point
* @param {Array} pt value
* @return {Array}
*/
function
getCoord
(
pt
)
{
return
sampleObject
.
charObj
.
convertToPixel
(
'
grid
'
,
pt
);
}
/**
* find nearest value
* @param {Array} eventPoint value
* @return {Object}
*/
function
findNearestValue
(
eventPoint
)
{
if
(
!
eventPoint
||
!
eventPoint
.
length
||
!
sampleObject
||
!
sampleObject
.
charObj
)
{
return
;
}
const
value
=
sampleObject
.
charObj
.
convertFromPixel
(
'
grid
'
,
eventPoint
);
let
binIndex
=
null
;
let
yIndex
=
null
;
let
nearestX
=
Infinity
;
let
nearestY
=
-
Infinity
;
let
nearestYData
=
Infinity
;
if
(
!
sampleObject
.
charData
.
oriData
||
!
value
||
!
value
.
length
)
{
return
;
}
const
gridRect
=
sampleObject
.
charObj
.
getModel
()
.
getComponent
(
'
grid
'
,
0
)
.
coordinateSystem
.
getRect
();
const
gridRectY
=
gridRect
.
y
-
10
;
const
x
=
value
[
0
];
chartData
.
forEach
((
dataItem
,
i
)
=>
{
let
distY
;
let
yAxis
;
for
(
let
k
=
0
;
k
<
dataItem
.
items
.
length
-
1
;
k
++
)
{
const
item
=
dataItem
.
items
[
k
];
const
itemNext
=
dataItem
.
items
[
k
+
1
];
const
nextX
=
itemNext
[
2
];
const
nextZ
=
itemNext
[
3
];
if
(
item
.
length
>=
4
)
{
if
(
item
[
2
]
<
x
&&
nextX
>=
x
)
{
const
proportionX
=
(
x
-
item
[
2
])
/
(
nextX
-
item
[
2
]);
yAxis
=
(
nextZ
-
item
[
3
])
*
proportionX
+
item
[
3
];
distY
=
Math
.
abs
(
value
[
1
]
-
yAxis
);
break
;
}
}
}
if
(
curViewName
===
0
&&
distY
<
nearestYData
)
{
nearestYData
=
distY
;
yIndex
=
i
;
}
else
if
(
curViewName
===
1
)
{
const
pt
=
getCoord
([
x
,
dataItem
.
step
]);
const
ptStep
=
pt
[
1
];
pt
[
1
]
-=
((
yAxis
-
charOption
.
minZ
)
/
(
charOption
.
maxZ
-
charOption
.
minZ
))
*
gridRectY
;
if
(
eventPoint
[
1
]
>
pt
[
1
]
&&
eventPoint
[
1
]
<
ptStep
&&
ptStep
>
nearestY
)
{
nearestY
=
ptStep
;
yIndex
=
i
;
}
}
});
if
(
yIndex
===
null
&&
curViewName
===
1
)
{
chartData
.
forEach
((
item
,
index
)
=>
{
if
(
item
.
step
>
value
[
1
])
{
yIndex
=
yIndex
===
null
?
index
:
Math
.
min
(
yIndex
,
index
);
}
});
}
if
(
yIndex
!==
null
)
{
const
yData
=
chartData
[
yIndex
].
items
;
yData
.
forEach
((
ele
,
index
)
=>
{
const
distX
=
Math
.
abs
(
ele
[
2
]
-
value
[
0
]);
if
(
distX
<
nearestX
)
{
nearestX
=
distX
;
binIndex
=
index
;
}
});
binIndex
=
binIndex
===
0
?
1
:
binIndex
===
yData
.
length
-
1
?
yData
.
length
-
2
:
binIndex
;
}
return
{
binIndex
,
yIndex
,
};
}
zr
.
on
(
'
mouseout
'
,
(
e
)
=>
{
if
(
!
rawData
||
!
rawData
.
length
)
{
return
;
}
this
.
chartTipFlag
=
false
;
this
.
removeTooltip
(
sampleIndex
);
});
zr
.
on
(
'
mousemove
'
,
(
e
)
=>
{
if
(
!
rawData
||
!
rawData
.
length
)
{
return
;
}
this
.
removeTooltip
(
sampleIndex
);
curViewName
=
this
.
curViewName
;
const
unit
=
'
s
'
;
const
nearestIndex
=
findNearestValue
([
e
.
offsetX
,
e
.
offsetY
]);
if
(
nearestIndex
&&
nearestIndex
.
yIndex
!==
null
&&
nearestIndex
.
binIndex
!==
null
)
{
const
{
binIndex
,
yIndex
}
=
nearestIndex
;
const
gridRect
=
sampleObject
.
charObj
.
getModel
()
.
getComponent
(
'
grid
'
,
0
)
.
coordinateSystem
.
getRect
();
const
gridRectY
=
gridRect
.
y
-
10
;
let
linePoints
=
[];
if
(
curViewName
===
1
&&
yIndex
!==
null
)
{
linePoints
=
this
.
makePolyPoints
(
yIndex
,
getCoord
,
gridRectY
,
charOption
,
);
}
else
if
(
curViewName
===
0
&&
chartData
[
yIndex
]
&&
chartData
[
yIndex
].
items
)
{
chartData
[
yIndex
].
items
.
forEach
((
item
)
=>
{
linePoints
.
push
(
sampleObject
.
charObj
.
convertToPixel
(
'
grid
'
,
[
item
[
2
],
item
[
3
]]),
);
});
}
this
.
zrDrawElement
.
hoverLine
=
new
echarts
.
graphic
.
Polyline
({
silent
:
true
,
shape
:
{
points
:
linePoints
.
slice
(
1
,
-
1
),
},
z
:
999
,
});
zr
.
add
(
this
.
zrDrawElement
.
hoverLine
);
this
.
zrDrawElement
.
tooltip
=
new
echarts
.
graphic
.
Text
({});
let
itemX
;
const
x
=
chartData
[
yIndex
].
items
[
binIndex
][
2
];
let
z
=
0
;
chartData
.
forEach
((
dataItem
,
index
)
=>
{
const
y
=
dataItem
.
step
;
const
pt
=
getCoord
([
x
,
y
]);
if
(
index
===
yIndex
)
{
z
=
chartData
[
yIndex
].
items
[
binIndex
][
3
];
}
else
{
const
items
=
dataItem
.
items
;
for
(
let
k
=
1
;
k
<
items
.
length
-
1
;
k
++
)
{
const
nextX
=
items
[
k
+
1
][
2
];
const
nextZ
=
items
[
k
+
1
][
3
];
if
(
items
[
k
][
2
]
===
x
)
{
z
=
items
[
k
][
3
];
break
;
}
else
if
(
items
[
k
][
2
]
<
x
&&
nextX
>
x
)
{
const
proportionX
=
(
x
-
items
[
k
][
2
])
/
(
nextX
-
items
[
k
][
2
]);
z
=
(
nextZ
-
items
[
k
][
3
])
*
proportionX
+
items
[
k
][
3
];
break
;
}
}
}
itemX
=
pt
[
0
];
const
circleOption
=
{
z
:
1000
,
};
if
(
curViewName
===
1
)
{
pt
[
1
]
-=
((
z
-
charOption
.
minZ
)
/
(
charOption
.
maxZ
-
charOption
.
minZ
))
*
gridRectY
;
circleOption
.
shape
=
{
cx
:
itemX
,
cy
:
pt
[
1
],
r
:
2
,
};
}
else
{
circleOption
.
shape
=
{
cx
:
0
,
cy
:
0
,
r
:
2
,
};
circleOption
.
position
=
sampleObject
.
charObj
.
convertToPixel
(
'
grid
'
,
[
x
,
z
],
);
}
const
dot
=
new
echarts
.
graphic
.
Circle
(
circleOption
);
zr
.
add
(
dot
);
this
.
zrDrawElement
.
hoverDots
.
push
(
dot
);
});
const
hoveredItem
=
chartData
[
yIndex
];
this
.
zrDrawElement
.
tooltip
=
new
echarts
.
graphic
.
Text
({});
if
(
!
this
.
chartTipFlag
)
{
this
.
chartTipFlag
=
true
;
}
if
(
!
hoveredItem
||
!
hoveredItem
.
items
[
binIndex
])
{
return
;
}
let
htmlStr
=
''
;
const
hoveredAxis
=
hoveredItem
.
items
[
binIndex
][
3
];
htmlStr
=
`<td>
${
hoveredAxis
.
toString
().
length
>=
6
?
yValueFormat
(
hoveredAxis
)
:
hoveredAxis
}
</td><td style="text-align:center;">
${
hoveredItem
.
step
}
</td><td>
${(
hoveredItem
.
relative_time
/
1000
).
toFixed
(
3
)}${
unit
}
</td><td>
${
this
.
dealrelativeTime
(
new
Date
(
hoveredItem
.
wall_time
).
toString
(),
)}
</td>`
;
const
dom
=
document
.
querySelector
(
'
#tipTr
'
);
dom
.
innerHTML
=
htmlStr
;
if
(
!
sampleObject
.
fullScreen
)
{
const
chartWidth
=
document
.
querySelectorAll
(
'
.sample-content
'
)[
sampleIndex
].
clientWidth
;
const
chartHeight
=
document
.
querySelectorAll
(
'
.sample-content
'
)[
sampleIndex
].
clientHeight
;
const
left
=
document
.
querySelectorAll
(
'
.sample-content
'
)[
sampleIndex
].
offsetLeft
;
const
top
=
document
.
querySelectorAll
(
'
.sample-content
'
)[
sampleIndex
].
offsetTop
;
const
echartTip
=
document
.
querySelector
(
'
#echartTip
'
);
echartTip
.
style
.
top
=
`
${
top
+
chartHeight
-
60
}
px`
;
if
(
left
>
echartTip
.
clientWidth
)
{
echartTip
.
style
.
left
=
`
${
left
-
echartTip
.
clientWidth
}
px`
;
}
else
{
echartTip
.
style
.
left
=
`
${
left
+
chartWidth
}
px`
;
}
}
else
{
const
width
=
document
.
querySelector
(
'
#echartTip
'
).
clientWidth
;
const
height
=
document
.
querySelector
(
'
#echartTip
'
).
clientHeight
;
const
screenWidth
=
document
.
body
.
scrollWidth
;
const
screenHeight
=
document
.
body
.
scrollHeight
;
const
scrollTop
=
document
.
querySelector
(
'
.cl-histogram-show-data-content
'
,
).
scrollTop
;
const
offsetTop
=
document
.
querySelector
(
'
.cl-histogram-show-data-content
'
,
).
offsetTop
;
if
(
height
+
e
.
event
.
y
+
20
>
screenHeight
&&
screenHeight
>
height
)
{
document
.
querySelector
(
'
#echartTip
'
).
style
.
top
=
`
${
e
.
event
.
y
+
scrollTop
-
height
-
20
-
offsetTop
}
px`
;
}
else
{
document
.
querySelector
(
'
#echartTip
'
).
style
.
top
=
`
${
e
.
event
.
y
+
scrollTop
+
20
-
offsetTop
}
px`
;
}
if
(
width
+
e
.
event
.
x
+
50
>
screenWidth
&&
screenWidth
>
width
)
{
document
.
querySelector
(
'
#echartTip
'
).
style
.
left
=
`
${
e
.
event
.
x
-
width
-
20
}
px`
;
}
else
{
document
.
querySelector
(
'
#echartTip
'
).
style
.
left
=
`
${
e
.
event
.
x
+
20
}
px`
;
}
}
this
.
zrDrawElement
.
tooltipX
=
new
echarts
.
graphic
.
Text
({
position
:
[
itemX
,
gridRect
.
y
+
gridRect
.
height
],
style
:
{
fontFamily
:
'
Merriweather Sans
'
,
text
:
Math
.
round
(
x
*
1000
)
/
1000
,
textFill
:
'
#fff
'
,
textAlign
:
'
center
'
,
fontSize
:
12
,
textBackgroundColor
:
'
#333
'
,
textBorderWidth
:
2
,
textPadding
:
[
5
,
7
],
rich
:
{},
},
z
:
2000
,
});
zr
.
add
(
this
.
zrDrawElement
.
tooltipX
);
if
(
curViewName
===
1
&&
linePoints
&&
linePoints
.
length
)
{
this
.
zrDrawElement
.
tooltipY
=
new
echarts
.
graphic
.
Text
({
position
:
[
gridRect
.
x
+
gridRect
.
width
,
linePoints
[
linePoints
.
length
-
1
][
1
],
],
style
:
{
fontFamily
:
'
Merriweather Sans
'
,
text
:
hoveredItem
.
step
,
textFill
:
'
#fff
'
,
textVerticalAlign
:
'
middle
'
,
fontSize
:
12
,
textBackgroundColor
:
'
#333
'
,
textBorderWidth
:
2
,
textPadding
:
[
5
,
7
],
rich
:
{},
},
z
:
2000
,
});
zr
.
add
(
this
.
zrDrawElement
.
tooltipY
);
}
}
});
},
dealrelativeTime
(
time
)
{
const
arr
=
time
.
split
(
'
'
);
const
str
=
arr
[
0
]
+
'
'
+
arr
[
1
]
+
'
'
+
arr
[
2
]
+
'
,
'
+
'
'
+
arr
[
4
];
return
str
;
},
/**
* remove tooltip
* @param {Number} sampleIndex sampleIndex
*/
removeTooltip
(
sampleIndex
)
{
const
sampleObject
=
this
.
originDataArr
[
sampleIndex
];
if
(
sampleObject
.
charObj
)
{
const
zr
=
sampleObject
.
charObj
.
getZr
();
if
(
this
.
zrDrawElement
.
hoverLine
)
{
zr
.
remove
(
this
.
zrDrawElement
.
hoverLine
);
}
if
(
this
.
zrDrawElement
.
tooltip
)
{
zr
.
remove
(
this
.
zrDrawElement
.
tooltip
);
}
if
(
this
.
zrDrawElement
.
tooltipY
)
{
zr
.
remove
(
this
.
zrDrawElement
.
tooltipY
);
}
if
(
this
.
zrDrawElement
.
hoverDots
&&
this
.
zrDrawElement
.
hoverDots
.
length
)
{
this
.
zrDrawElement
.
hoverDots
.
forEach
((
dot
)
=>
zr
.
remove
(
dot
));
this
.
zrDrawElement
.
hoverDots
.
length
=
0
;
}
if
(
this
.
zrDrawElement
.
tooltipX
)
{
zr
.
remove
(
this
.
zrDrawElement
.
tooltipX
);
}
}
},
getValue
(
seriesData
,
dataIndex
,
i
)
{
return
seriesData
[
dataIndex
][
i
];
},
makePolyPoints
(
dataIndex
,
getCoord
,
yValueMapHeight
,
charOption
)
{
const
points
=
[];
const
rawData
=
charOption
.
seriesData
;
const
maxZ
=
charOption
.
maxZ
;
const
minZ
=
charOption
.
minZ
;
for
(
let
i
=
0
;
i
<
rawData
[
dataIndex
].
length
;
)
{
const
x
=
this
.
getValue
(
rawData
,
dataIndex
,
i
++
);
const
y
=
this
.
getValue
(
rawData
,
dataIndex
,
i
++
);
const
z
=
this
.
getValue
(
rawData
,
dataIndex
,
i
++
);
const
pt
=
getCoord
([
x
,
y
]);
// linear map in z axis
pt
[
1
]
-=
((
z
-
minZ
)
/
(
maxZ
-
minZ
))
*
yValueMapHeight
;
points
.
push
(
pt
);
}
return
points
;
},
formOriData
(
dataItem
)
{
const
chartData
=
[];
const
wallTimeInit
=
dataItem
.
histograms
.
length
?
dataItem
.
histograms
[
0
].
wall_time
:
0
;
dataItem
.
histograms
.
forEach
((
histogram
,
index
)
=>
{
const
chartItem
=
{
wall_time
:
histogram
.
wall_time
,
relative_time
:
histogram
.
wall_time
-
wallTimeInit
,
step
:
histogram
.
step
,
items
:
[],
};
const
chartArr
=
[];
histogram
.
buckets
.
forEach
((
bucket
)
=>
{
const
xData
=
bucket
[
0
]
+
bucket
[
1
]
/
2
;
const
filter
=
chartArr
.
filter
((
k
)
=>
k
[
0
]
===
xData
);
if
(
!
filter
.
length
)
{
chartArr
.
push
([
histogram
.
wall_time
,
histogram
.
step
,
xData
,
Math
.
floor
(
bucket
[
2
]),
]);
}
});
chartArr
.
sort
((
a
,
b
)
=>
a
[
0
]
-
b
[
0
]);
if
(
chartArr
.
length
)
{
const
minItem
=
chartArr
[
0
][
2
];
const
maxItem
=
chartArr
[
chartArr
.
length
-
1
][
2
];
const
chartAll
=
[
[
histogram
.
wall_time
,
histogram
.
step
,
minItem
,
0
],
].
concat
(
chartArr
,
[
[
histogram
.
wall_time
,
histogram
.
step
,
maxItem
,
0
],
]);
chartItem
.
items
=
chartAll
;
chartData
.
push
(
chartItem
);
}
});
return
{
tag
:
dataItem
.
tag
,
train_id
:
dataItem
.
train_id
,
chartData
};
},
formatDataToChar
(
dataIndex
)
{
const
dataItem
=
this
.
originDataArr
[
dataIndex
].
charData
.
oriData
;
const
title
=
this
.
originDataArr
[
dataIndex
].
tagName
;
const
seriesData
=
[];
let
maxStep
=
-
Infinity
;
let
minStep
=
Infinity
;
let
maxX
=
-
Infinity
;
let
minX
=
Infinity
;
let
maxZ
=
-
Infinity
;
let
minZ
=
Infinity
;
const
girdData
=
[];
if
(
dataItem
.
chartData
&&
dataItem
.
chartData
.
length
)
{
dataItem
.
chartData
.
forEach
((
histogram
)
=>
{
const
seriesItem
=
[];
girdData
.
push
([
histogram
.
step
,
histogram
.
relative_time
,
histogram
.
wall_time
,
]);
maxStep
=
Math
.
max
(
maxStep
,
histogram
.
step
);
minStep
=
Math
.
min
(
minStep
,
histogram
.
step
);
histogram
.
items
.
forEach
((
bucket
)
=>
{
if
(
this
.
curViewName
===
0
)
{
seriesItem
.
push
([
bucket
[
2
],
bucket
[
3
]]);
}
else
if
(
this
.
curViewName
===
1
)
{
seriesItem
.
push
(
bucket
[
2
],
histogram
.
step
,
bucket
[
3
]);
}
maxX
=
Math
.
max
(
maxX
,
bucket
[
2
]);
minX
=
Math
.
min
(
minX
,
bucket
[
2
]);
minZ
=
Math
.
min
(
minZ
,
bucket
[
3
]);
maxZ
=
Math
.
max
(
maxZ
,
bucket
[
3
]);
});
seriesData
.
push
(
seriesItem
);
});
}
return
{
title
,
seriesData
,
maxStep
,
minStep
,
maxX
,
minX
,
maxZ
,
minZ
,
girdData
,
};
},
formatCharOption
(
sampleIndex
,
charOption
)
{
const
sampleObject
=
this
.
originDataArr
[
sampleIndex
];
const
fullScreenFun
=
this
.
toggleFullScreen
;
const
curAxisName
=
this
.
curAxisName
;
const
option
=
{
textStyle
:
{
fontFamily
:
'
Merriweather Sans
'
},
title
:
{
text
:
charOption
.
title
||
''
,
textStyle
:
{
fontSize
:
'
16
'
,
fontWeight
:
'
600
'
,
bottom
:
6
,
left
:
'
center
'
,
},
},
grid
:
{
left
:
15
,
top
:
60
,
right
:
40
,
bottom
:
60
,
},
color
:
[
'
#346E69
'
],
xAxis
:
{
max
:
charOption
.
maxX
,
min
:
charOption
.
minX
,
axisLine
:
{
onZero
:
false
},
axisLabel
:
{
fontSize
:
'
11
'
,
formatter
:
function
(
value
)
{
return
Math
.
round
(
value
*
100
)
/
100
;
},
},
splitLine
:
{
show
:
false
},
},
yAxis
:
{
position
:
'
right
'
,
axisLine
:
{
onZero
:
false
,
show
:
false
},
splitLine
:
{
show
:
true
},
axisTick
:
{
show
:
false
},
axisLabel
:
{
fontSize
:
'
11
'
,
},
},
toolbox
:
{
top
:
20
,
right
:
20
,
emphasis
:
{
iconStyle
:
{
textPosition
:
'
top
'
,
},
},
// toolbox
feature
:
{
// fullScreen
myToolFullScreen
:
{
show
:
true
,
title
:
this
.
$t
(
'
histogram.fullScreen
'
),
iconStyle
:
{
borderColor
:
sampleObject
.
fullScreen
?
'
#3E98C5
'
:
'
#6D7278
'
,
},
icon
:
CommonProperty
.
fullScreenIcon
,
onclick
()
{
fullScreenFun
(
sampleIndex
);
},
},
},
},
};
if
(
this
.
curViewName
===
1
)
{
option
.
series
=
[
{
type
:
'
custom
'
,
dimensions
:
[
'
x
'
,
'
y
'
],
renderItem
:
(
params
,
api
)
=>
{
const
points
=
this
.
makePolyPoints
(
params
.
dataIndex
,
api
.
coord
,
params
.
coordSys
.
y
-
10
,
charOption
,
);
return
{
type
:
'
polyline
'
,
silent
:
true
,
shape
:
{
points
,
},
style
:
api
.
style
({
stroke
:
'
#bbb
'
,
lineWidth
:
1
,
}),
};
},
data
:
charOption
.
seriesData
,
},
];
option
.
grid
.
top
=
126
;
if
(
curAxisName
===
2
&&
sampleObject
.
fullScreen
)
{
option
.
grid
.
right
=
140
;
}
option
.
yAxis
.
inverse
=
true
;
const
that
=
this
;
option
.
yAxis
.
axisLabel
.
formatter
=
function
(
value
)
{
let
data
=
''
;
const
filter
=
sampleObject
.
charData
.
oriData
.
chartData
.
filter
(
(
k
)
=>
k
.
step
===
value
,
);
if
(
filter
.
length
)
{
if
(
curAxisName
===
2
)
{
data
=
sampleObject
.
fullScreen
?
that
.
dealrelativeTime
(
new
Date
(
filter
[
0
].
wall_time
).
toString
(),
)
:
[];
}
else
if
(
curAxisName
===
1
)
{
data
=
(
filter
[
0
].
relative_time
/
1000
).
toFixed
(
3
);
}
else
{
data
=
filter
[
0
].
step
;
}
}
return
data
;
};
option
.
visualMap
=
{
type
:
'
continuous
'
,
show
:
false
,
min
:
charOption
.
minStep
,
max
:
charOption
.
maxStep
,
dimension
:
1
,
range
:
[
charOption
.
minStep
,
charOption
.
maxStep
],
inRange
:
{
colorLightness
:
[
0.3
,
0.9
],
},
};
}
else
if
(
this
.
curViewName
===
0
)
{
option
.
series
=
[];
charOption
.
seriesData
.
forEach
((
k
)
=>
{
option
.
series
.
push
({
type
:
'
line
'
,
symbol
:
'
none
'
,
lineStyle
:
{
width
:
1
,
},
data
:
k
.
slice
(
1
,
-
1
),
});
});
}
return
option
;
},
toggleFullScreen
(
sampleIndex
)
{
const
sampleObject
=
this
.
originDataArr
[
sampleIndex
];
if
(
!
sampleObject
)
{
return
;
}
sampleObject
.
fullScreen
=
!
sampleObject
.
fullScreen
;
if
(
sampleObject
.
fullScreen
)
{
if
(
this
.
curAxisName
===
2
)
{
sampleObject
.
charObj
.
setOption
({
grid
:
{
right
:
140
}});
}
sampleObject
.
charData
.
charOption
.
toolbox
.
feature
.
myToolFullScreen
.
iconStyle
.
borderColor
=
'
#3E98C5
'
;
}
else
{
sampleObject
.
charObj
.
setOption
({
grid
:
{
right
:
40
}});
sampleObject
.
charData
.
charOption
.
toolbox
.
feature
.
myToolFullScreen
.
iconStyle
.
borderColor
=
'
#6D7278
'
;
}
setTimeout
(()
=>
{
sampleObject
.
charObj
.
resize
();
document
.
getElementById
(
sampleObject
.
domId
).
scrollIntoView
();
},
0
);
},
},
};
</
script
>
<
style
lang=
"scss"
>
.cl-histogram-manage
{
height
:
100%
;
.histogram-bk
{
height
:
100%
;
background-color
:
#fff
;
display
:
flex
;
flex-direction
:
column
;
.cl-histogram-title
{
height
:
56px
;
line-height
:
56px
;
.cl-close-btn
{
width
:
20px
;
height
:
20px
;
vertical-align
:
-3px
;
cursor
:
pointer
;
display
:
inline-block
;
}
}
.cl-histogram-operate-content
{
width
:
100%
;
padding
:
8px
32px
22px
32px
;
background
:
#ffffff
;
}
.cl-histogram-view-type-select-content
{
background
:
#ffffff
;
padding
:
0
32px
21px
32px
;
height
:
58px
;
display
:
flex
;
align-items
:
center
;
border-bottom
:
2px
solid
#e6ebf5
;
.view-title
{
font-size
:
14px
;
line-height
:
14px
;
vertical-align
:
middle
;
margin-right
:
16px
;
flex-shrink
:
0
;
}
.el-radio-group
{
margin-right
:
64px
;
flex-shrink
:
0
;
}
}
.cl-histogram-show-data-content
{
background
:
#ffffff
;
padding
:
0
23px
;
flex
:
1
;
overflow
:
auto
;
.data-content
{
display
:
flex
;
height
:
100%
;
width
:
100%
;
flex-wrap
:
wrap
;
min-height
:
400px
;
position
:
relative
;
.sample-content
{
width
:
33
.3%
;
height
:
400px
;
display
:
flex
;
flex-direction
:
column
;
flex-shrink
:
0
;
background-color
:
#fff
;
position
:
relative
;
}
.char-full-screen
{
width
:
100%
;
height
:
400px
;
}
.chars-container
{
flex
:
1
;
padding
:
0
15px
0
15px
;
position
:
relative
;
.char-item-content
{
width
:
100%
;
height
:
100%
;
}
}
}
}
.pagination-content
{
padding
:
24px
32px
;
text-align
:
right
;
}
.image-noData
{
width
:
100%
;
height
:
450px
;
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
flex-direction
:
column
;
}
}
.content
{
position
:
relative
;
}
#echart
{
width
:
500px
;
height
:
500px
;
border
:
1px
solid
black
;
position
:
relative
;
}
#echartTip
{
position
:
absolute
;
padding
:
5px
;
z-index
:
9999
;
font-size
:
14px
;
font-family
:
'Microsoft YaHei'
;
background-color
:
rgba
(
50
,
50
,
50
,
0
.7
);
border
:
0
;
border-radius
:
4px
;
color
:
#fff
;
}
.char-tip-table
td
{
padding-left
:
5px
;
padding-right
:
5px
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
max-width
:
150px
;
overflow
:
hidden
;
}
.borderspacing3
{
border-spacing
:
3px
;
}
}
</
style
>
mindinsight/ui/src/views/train-manage/image.vue
浏览文件 @
5c27dcc9
...
...
@@ -28,9 +28,9 @@ limitations under the License.
</div>
<!-- Selecting an operation area -->
<div
class=
"cl-img-operate-content"
>
<
checkListComponents
ref=
"checkList
Components"
<
multiselectGroupComponents
ref=
"multiselectGroup
Components"
:checkListArr=
"tagOperateList"
@
selectedChange=
"tagSelectedChanged"
></
checkList
Components>
@
selectedChange=
"tagSelectedChanged"
></
multiselectGroup
Components>
</div>
<!-- Sliding block area -->
<div
class=
"cl-img-slider-operate-content"
>
...
...
@@ -124,7 +124,7 @@ limitations under the License.
</
template
>
<
script
>
import
checkListComponents
from
'
../../components/checkList
.vue
'
;
import
multiselectGroupComponents
from
'
../../components/multiselectGroup
.vue
'
;
import
RequestService
from
'
../../services/request-service
'
;
import
{
basePath
}
from
'
@/services/fetcher
'
;
export
default
{
...
...
@@ -279,7 +279,7 @@ export default {
this
.
initOver
=
true
;
this
.
$nextTick
(()
=>
{
this
.
multiSelectedTagNames
=
this
.
$refs
.
checkList
Components
.
updateSelectedDic
();
this
.
multiSelectedTagNames
=
this
.
$refs
.
multiselectGroup
Components
.
updateSelectedDic
();
// Obtains data on the current page
this
.
updateTagInPage
();
});
...
...
@@ -583,7 +583,7 @@ export default {
// Check whether new data exists and add it
const
dataAddFlag
=
this
.
checkNewDataAndComplete
(
oriData
);
this
.
$nextTick
(()
=>
{
this
.
multiSelectedTagNames
=
this
.
$refs
.
checkList
Components
.
updateSelectedDic
();
this
.
multiSelectedTagNames
=
this
.
$refs
.
multiselectGroup
Components
.
updateSelectedDic
();
this
.
updateTagInPage
(
!
dataRemoveFlag
&&
!
dataAddFlag
);
});
},
this
.
requestErrorCallback
)
...
...
@@ -624,7 +624,7 @@ export default {
},
},
components
:
{
checkList
Components
,
multiselectGroup
Components
,
},
};
</
script
>
...
...
mindinsight/ui/src/views/train-manage/training-dashboard.vue
浏览文件 @
5c27dcc9
...
...
@@ -50,6 +50,24 @@ limitations under the License.
</div>
</div>
</div>
<div
class=
"cl-dashboard-con-up"
:class=
"!!histogramTag ? '' : 'no-data-hover'"
@
click=
"viewMoreHistogram"
>
<div
class=
"cl-dashboard-title"
>
{{
$t
(
"
histogram.titleText
"
)
}}
</div>
<div
class=
"cl-module"
>
<div
id=
"distribution-chart"
v-show=
"!!histogramTag"
></div>
<div
class=
"no-data-img"
key=
"no-chart-data"
v-show=
"!histogramTag"
>
<img
:src=
"require('@/assets/images/nodata.png')"
alt=
""
/>
<p
class=
'no-data-text'
>
{{
$t
(
"
public.noData
"
)
}}
</p>
</div>
</div>
</div>
<div
class=
"cl-dashboard-con-up"
:class=
"firstFloorNodes.length && !wrongPlugin ? '' : 'no-data-hover'"
@
click=
"jumpToGraph"
>
...
...
@@ -118,6 +136,16 @@ limitations under the License.
</div>
</div>
</div>
<div
class=
"cl-dashboard-con-up no-data-hover"
>
<div
class=
"comming-soon-content"
>
<div
class=
"comming-soon-container"
>
<img
:src=
"require('@/assets/images/comming-soon.png')"
/>
<p
class=
'comming-soon-text'
>
{{
$t
(
"
public.stayTuned
"
)
}}
</p>
</div>
</div>
</div>
</div>
</div>
</
template
>
...
...
@@ -126,11 +154,10 @@ limitations under the License.
import
RequestService
from
'
@/services/request-service
'
;
import
{
basePath
}
from
'
@/services/fetcher
'
;
import
CommonProperty
from
'
@/common/common-property.js
'
;
import
{
select
,
selectAll
}
from
'
d3
'
;
import
{
select
,
selectAll
,
format
,
precisionRound
}
from
'
d3
'
;
import
'
d3-graphviz
'
;
const
d3
=
{
select
,
selectAll
};
const
d3
=
{
select
,
selectAll
,
format
,
precisionRound
};
import
echarts
from
'
echarts
'
;
export
default
{
data
()
{
return
{
...
...
@@ -139,7 +166,9 @@ export default {
defColorCount
:
CommonProperty
.
commonColorArr
.
length
,
// default color
colorNum
:
0
,
charObj
:
null
,
valDistChar
:
null
,
histogramObj
:
null
,
histogramOption
:
{},
histogramData
:
{},
charOption
:
{},
charData
:
[],
originImageDataArr
:
[],
// List of all image data.
...
...
@@ -147,6 +176,7 @@ export default {
imageRandomLoopCount
:
0
,
imageBasePath
:
'
/v1/mindinsight/datavisual/image/single-image?
'
,
// Relative path header of the picture
autoUpdateTimer
:
null
,
// Automatic refresh timer
histogramTag
:
''
,
// Label of the currently displayed histogram.
allGraphData
:
{},
// graph Original input data
graphviz
:
null
,
firstFloorNodes
:
[],
// ID array of the first layer node.
...
...
@@ -158,6 +188,7 @@ export default {
datasetGraphviz
:
{},
reloadStopTime
:
1000
,
wrongPlugin
:
false
,
fileTag
:
''
,
};
},
computed
:
{
...
...
@@ -236,8 +267,8 @@ export default {
if
(
this
.
charObj
)
{
this
.
charObj
.
resize
();
}
if
(
this
.
valDistChar
)
{
this
.
valDistChar
.
resize
();
if
(
this
.
histogramObj
)
{
this
.
histogramObj
.
resize
();
}
},
500
);
},
...
...
@@ -279,14 +310,23 @@ export default {
const
imageTags
=
data
.
image
||
[];
const
scalarTags
=
data
.
scalar
||
[];
const
graphIds
=
data
.
graph
||
[];
if
(
graphIds
.
length
)
{
this
.
fileTag
=
graphIds
[
0
];
}
const
histogramTags
=
data
.
histogram
||
[];
this
.
getHistogramTag
(
histogramTags
);
this
.
dealImageData
(
imageTags
);
this
.
getScalarList
(
scalarTags
);
if
(
!
this
.
firstFloorNodes
.
length
&&
graphIds
.
length
)
{
this
.
queryGraphData
();
}
})
.
catch
((
error
)
=>
{
if
(
!
error
.
response
||
!
error
.
response
.
data
||
!
error
.
response
.
data
.
error_code
)
{
.
catch
((
error
)
=>
{
if
(
!
error
.
response
||
!
error
.
response
.
data
||
!
error
.
response
.
data
.
error_code
)
{
return
;
}
if
(
error
.
response
.
data
.
error_code
.
toString
()
===
'
50545005
'
)
{
...
...
@@ -309,6 +349,20 @@ export default {
},
});
},
/**
* Viewing more histogram information
*/
viewMoreHistogram
()
{
if
(
!
this
.
histogramTag
)
{
return
;
}
this
.
$router
.
push
({
path
:
'
/train-manage/histogram
'
,
query
:
{
train_id
:
this
.
trainingJobId
,
},
});
},
/**
* Go to data.
*/
...
...
@@ -711,6 +765,223 @@ export default {
this
.
originImageDataArr
=
dataList
;
this
.
getSampleRandomly
();
},
getHistogramTag
(
tagList
)
{
if
(
!
tagList
)
{
return
;
}
if
(
!
this
.
histogramTag
||
tagList
.
indexOf
(
this
.
histogramTag
)
===
-
1
)
{
this
.
histogramTag
=
tagList
[
0
]
||
''
;
}
if
(
!
this
.
histogramTag
)
{
return
;
}
const
params
=
{
train_id
:
this
.
trainingJobId
,
tag
:
this
.
histogramTag
,
};
// tag
RequestService
.
getHistogramData
(
params
).
then
((
res
)
=>
{
if
(
!
res
||
!
res
.
data
||
!
res
.
data
.
histograms
||
!
res
.
data
.
histograms
.
length
)
{
return
;
}
const
data
=
res
.
data
;
this
.
histogramData
=
this
.
formOriData
(
data
);
const
charOption
=
this
.
formatDataToChar
();
this
.
updateHistogramSampleData
(
charOption
);
});
},
formOriData
(
dataItem
)
{
const
chartData
=
[];
dataItem
.
histograms
.
forEach
((
histogram
,
index
)
=>
{
const
chartItem
=
{
wall_time
:
histogram
.
wall_time
,
step
:
histogram
.
step
,
items
:
[],
};
const
chartArr
=
[];
histogram
.
buckets
.
forEach
((
bucket
)
=>
{
const
xData
=
bucket
[
0
]
+
bucket
[
1
]
/
2
;
const
filter
=
chartArr
.
filter
((
k
)
=>
k
[
0
]
===
xData
);
if
(
!
filter
.
length
)
{
chartArr
.
push
([
histogram
.
wall_time
,
histogram
.
step
,
xData
,
Math
.
floor
(
bucket
[
2
]),
]);
}
});
chartArr
.
sort
((
a
,
b
)
=>
a
[
0
]
-
b
[
0
]);
if
(
chartArr
.
length
)
{
const
minItem
=
chartArr
[
0
][
2
];
const
maxItem
=
chartArr
[
chartArr
.
length
-
1
][
2
];
const
chartAll
=
[
[
histogram
.
wall_time
,
histogram
.
step
,
minItem
,
0
],
].
concat
(
chartArr
,
[
[
histogram
.
wall_time
,
histogram
.
step
,
maxItem
,
0
],
]);
chartItem
.
items
=
chartAll
;
chartData
.
push
(
chartItem
);
}
});
return
{
tag
:
dataItem
.
tag
,
train_id
:
dataItem
.
train_id
,
chartData
};
},
formatDataToChar
()
{
const
dataItem
=
this
.
histogramData
;
const
title
=
dataItem
.
tag
;
const
seriesData
=
[];
let
maxStep
=
-
Infinity
;
let
minStep
=
Infinity
;
let
maxX
=
-
Infinity
;
let
minX
=
Infinity
;
let
maxZ
=
-
Infinity
;
let
minZ
=
Infinity
;
if
(
dataItem
.
chartData
&&
dataItem
.
chartData
.
length
)
{
dataItem
.
chartData
.
forEach
((
histogram
)
=>
{
const
seriesItem
=
[];
maxStep
=
Math
.
max
(
maxStep
,
histogram
.
step
);
minStep
=
Math
.
min
(
minStep
,
histogram
.
step
);
histogram
.
items
.
sort
((
a
,
b
)
=>
a
[
0
]
-
b
[
0
]);
histogram
.
items
.
forEach
((
bucket
)
=>
{
seriesItem
.
push
(
bucket
[
2
],
histogram
.
step
,
bucket
[
3
]);
maxX
=
Math
.
max
(
maxX
,
bucket
[
2
]);
minX
=
Math
.
min
(
minX
,
bucket
[
2
]);
minZ
=
Math
.
min
(
minZ
,
bucket
[
3
]);
maxZ
=
Math
.
max
(
maxZ
,
bucket
[
3
]);
});
seriesData
.
push
(
seriesItem
);
});
}
return
{
title
,
seriesData
,
maxStep
,
minStep
,
maxX
,
minX
,
maxZ
,
minZ
,
};
},
formatCharOption
(
charOption
)
{
const
option
=
{
textStyle
:
{
fontFamily
:
'
Merriweather Sans
'
},
title
:
{
text
:
charOption
.
title
||
''
,
textStyle
:
{
fontSize
:
'
16
'
,
fontWeight
:
'
600
'
},
bottom
:
6
,
left
:
'
center
'
,
},
grid
:
{
left
:
15
,
top
:
126
,
right
:
40
,
bottom
:
60
,
},
color
:
[
'
#346E69
'
],
xAxis
:
{
max
:
charOption
.
maxX
,
min
:
charOption
.
minX
,
axisLine
:
{
onZero
:
false
},
axisLabel
:
{
fontSize
:
'
11
'
,
formatter
:
function
(
value
)
{
return
Math
.
round
(
value
*
100
)
/
100
;
},
},
splitLine
:
{
show
:
false
},
},
yAxis
:
{
position
:
'
right
'
,
axisLine
:
{
onZero
:
false
,
show
:
false
},
splitLine
:
{
show
:
true
},
inverse
:
true
,
axisTick
:
{
show
:
false
},
axisLabel
:
{
fontSize
:
'
11
'
,
},
},
visualMap
:
{
type
:
'
continuous
'
,
show
:
false
,
min
:
charOption
.
minStep
,
max
:
charOption
.
maxStep
,
dimension
:
1
,
range
:
[
charOption
.
minStep
,
charOption
.
maxStep
],
inRange
:
{
colorLightness
:
[
0.3
,
0.9
],
},
},
series
:
[
{
type
:
'
custom
'
,
dimensions
:
[
'
x
'
,
'
y
'
],
renderItem
:
(
params
,
api
)
=>
{
const
points
=
this
.
makePolyPoints
(
params
.
dataIndex
,
api
.
coord
,
params
.
coordSys
.
y
-
10
,
charOption
,
);
return
{
type
:
'
polyline
'
,
silent
:
true
,
shape
:
{
points
,
},
style
:
api
.
style
({
stroke
:
'
#bbb
'
,
lineWidth
:
1
,
}),
};
},
data
:
charOption
.
seriesData
,
},
],
};
return
option
;
},
/**
* update sample data
* @param {Object} charOption data
*/
updateHistogramSampleData
(
charOption
)
{
this
.
histogramOption
=
this
.
formatCharOption
(
charOption
);
setTimeout
(()
=>
{
if
(
!
this
.
histogramObj
)
{
this
.
histogramObj
=
echarts
.
init
(
document
.
getElementById
(
'
distribution-chart
'
),
null
,
);
}
this
.
histogramObj
.
setOption
(
this
.
histogramOption
,
true
);
},
100
);
},
getValue
(
seriesData
,
dataIndex
,
i
)
{
return
seriesData
[
dataIndex
][
i
];
},
makePolyPoints
(
dataIndex
,
getCoord
,
yValueMapHeight
,
charOption
)
{
const
points
=
[];
const
rawData
=
charOption
.
seriesData
;
const
maxZ
=
charOption
.
maxZ
;
const
minZ
=
charOption
.
minZ
;
for
(
let
i
=
0
;
i
<
rawData
[
dataIndex
].
length
;
)
{
const
x
=
this
.
getValue
(
rawData
,
dataIndex
,
i
++
);
const
y
=
this
.
getValue
(
rawData
,
dataIndex
,
i
++
);
const
z
=
this
.
getValue
(
rawData
,
dataIndex
,
i
++
);
const
pt
=
getCoord
([
x
,
y
]);
// linear map in z axis
pt
[
1
]
-=
((
z
-
minZ
)
/
(
maxZ
-
minZ
))
*
yValueMapHeight
;
points
.
push
(
pt
);
}
return
points
;
},
/**
* errorScalar
* @param {Object} error Error Object
...
...
@@ -886,6 +1157,7 @@ export default {
const
params
=
{
train_id
:
this
.
trainingJobId
,
type
:
'
name_scope
'
,
tag
:
this
.
fileTag
,
};
RequestService
.
queryGraphData
(
params
)
.
then
(
...
...
@@ -1436,7 +1708,7 @@ export default {
cursor
:
pointer
;
overflow
:
hidden
;
height
:
calc
(
50%
-
2px
);
width
:
calc
(
50
%
-
2px
);
width
:
calc
(
33
.3
%
-
2px
);
margin
:
1px
;
float
:
left
;
}
...
...
@@ -1524,6 +1796,20 @@ export default {
}
}
.comming-soon-content
{
width
:
100%
;
height
:
100%
;
text-align
:
center
;
.comming-soon-container
{
position
:
relative
;
top
:
calc
(
50%
-
88px
);
.comming-soon-text
{
color
:
#000000
;
font-size
:
16px
;
}
}
}
.no-data-hover
{
cursor
:
not
-
allowed
;
}
...
...
@@ -1549,6 +1835,12 @@ export default {
cursor
:
pointer
;
}
}
#distribution-chart
{
height
:
100%
;
canvas
{
cursor
:
pointer
;
}
}
#dataMapGraph
{
.CreatDataset
>
polygon
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录