Commit 70695fe0 authored by Lijiao's avatar Lijiao Committed by xuehui
Browse files

[WebUI] Add intermediate result and optimize hyper-parameter graph (#892)

* [WebUI] Add intermediate result and optimize hyper-parameter graph

* update

* fix comment
parent a65532ca
...@@ -2,10 +2,7 @@ import * as React from 'react'; ...@@ -2,10 +2,7 @@ import * as React from 'react';
import axios from 'axios'; import axios from 'axios';
import { Row, Col } from 'antd'; import { Row, Col } from 'antd';
import { MANAGER_IP } from '../static/const'; import { MANAGER_IP } from '../static/const';
import { import { Experiment, TableObj, Parameters, TrialNumber } from '../static/interface';
Experiment, TableObj,
Parameters, TrialNumber
} from '../static/interface';
import { getFinal } from '../static/function'; import { getFinal } from '../static/function';
import SuccessTable from './overview/SuccessTable'; import SuccessTable from './overview/SuccessTable';
import Title1 from './overview/Title1'; import Title1 from './overview/Title1';
...@@ -117,7 +114,9 @@ class Overview extends React.Component<{}, OverviewState> { ...@@ -117,7 +114,9 @@ class Overview extends React.Component<{}, OverviewState> {
clusterMetaData: clusterMetaData ? clusterMetaData : undefined clusterMetaData: clusterMetaData ? clusterMetaData : undefined
}); });
// search space format loguniform max and min // search space format loguniform max and min
const searchSpace = JSON.parse(sessionData.params.searchSpace); const temp = sessionData.params.searchSpace;
const searchSpace = temp !== undefined
? JSON.parse(temp) : {};
Object.keys(searchSpace).map(item => { Object.keys(searchSpace).map(item => {
const key = searchSpace[item]._type; const key = searchSpace[item]._type;
let value = searchSpace[item]._value; let value = searchSpace[item]._value;
......
...@@ -141,6 +141,7 @@ class SlideBar extends React.Component<{}, SliderState> { ...@@ -141,6 +141,7 @@ class SlideBar extends React.Component<{}, SliderState> {
} }
}); });
} }
getNNIversion = () => { getNNIversion = () => {
axios(`${MANAGER_IP}/version`, { axios(`${MANAGER_IP}/version`, {
method: 'GET' method: 'GET'
...@@ -233,7 +234,6 @@ class SlideBar extends React.Component<{}, SliderState> { ...@@ -233,7 +234,6 @@ class SlideBar extends React.Component<{}, SliderState> {
</a> </a>
<span className="version">Version: {version}</span> <span className="version">Version: {version}</span>
</Col> </Col>
</Row> </Row>
); );
} }
......
This diff is collapsed.
...@@ -2,7 +2,7 @@ import * as React from 'react'; ...@@ -2,7 +2,7 @@ import * as React from 'react';
interface Title1Props { interface Title1Props {
text: string; text: string;
icon: string; icon?: string;
bgcolor?: string; bgcolor?: string;
} }
......
import * as React from 'react';
import ReactEcharts from 'echarts-for-react';
import { TableObj, DetailAccurPoint, TooltipForAccuracy } from '../../static/interface';
require('echarts/lib/chart/scatter');
require('echarts/lib/component/tooltip');
require('echarts/lib/component/title');
interface DefaultPointProps {
showSource: Array<TableObj>;
height: number;
}
interface DefaultPointState {
defaultSource: object;
accNodata: string;
}
class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState> {
public _isMounted = false;
constructor(props: DefaultPointProps) {
super(props);
this.state = {
defaultSource: {},
accNodata: 'No data'
};
}
defaultMetric = (showSource: Array<TableObj>) => {
const accSource: Array<DetailAccurPoint> = [];
Object.keys(showSource).map(item => {
const temp = showSource[item];
if (temp.status === 'SUCCEEDED' && temp.acc.default !== undefined) {
const searchSpace = temp.description.parameters;
accSource.push({
acc: temp.acc.default,
index: temp.sequenceId,
searchSpace: JSON.stringify(searchSpace)
});
}
});
const resultList: Array<number | string>[] = [];
Object.keys(accSource).map(item => {
const items = accSource[item];
let temp: Array<number | string>;
temp = [items.index, items.acc, JSON.parse(items.searchSpace)];
resultList.push(temp);
});
const allAcuracy = {
grid: {
left: '8%'
},
tooltip: {
trigger: 'item',
enterable: true,
position: function (point: Array<number>, data: TooltipForAccuracy) {
if (data.data[0] < resultList.length / 2) {
return [point[0], 80];
} else {
return [point[0] - 300, 80];
}
},
formatter: function (data: TooltipForAccuracy) {
const result = '<div class="tooldetailAccuracy">' +
'<div>Trial No: ' + data.data[0] + '</div>' +
'<div>Default Metric: ' + data.data[1] + '</div>' +
'<div>Parameters: ' +
'<pre>' + JSON.stringify(data.data[2], null, 4) + '</pre>' +
'</div>' +
'</div>';
return result;
}
},
xAxis: {
name: 'Trial',
type: 'category',
},
yAxis: {
name: 'Default Metric',
type: 'value',
},
series: [{
symbolSize: 6,
type: 'scatter',
data: resultList
}]
};
if (this._isMounted === true) {
this.setState({ defaultSource: allAcuracy }, () => {
if (resultList.length === 0) {
this.setState({
accNodata: 'No data'
});
} else {
this.setState({
accNodata: ''
});
}
});
}
}
// update parent component state
componentWillReceiveProps(nextProps: DefaultPointProps) {
const showSource = nextProps.showSource;
this.defaultMetric(showSource);
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
render() {
const { height } = this.props;
const { defaultSource, accNodata } = this.state;
return (
<div>
<ReactEcharts
option={defaultSource}
style={{
width: '100%',
height: height,
margin: '0 auto',
}}
theme="my_theme"
notMerge={true} // update now
/>
<div className="showMess">{accNodata}</div>
</div>
);
}
}
export default DefaultPoint;
\ No newline at end of file
import * as React from 'react'; import * as React from 'react';
import axios from 'axios';
import { MANAGER_IP } from '../../static/const';
import ReactEcharts from 'echarts-for-react'; import ReactEcharts from 'echarts-for-react';
const echarts = require('echarts/lib/echarts'); import { TableObj } from 'src/static/interface';
require('echarts/lib/chart/bar'); require('echarts/lib/chart/bar');
require('echarts/lib/component/tooltip'); require('echarts/lib/component/tooltip');
require('echarts/lib/component/title'); require('echarts/lib/component/title');
echarts.registerTheme('my_theme', {
color: '#3c8dbc'
});
interface Runtrial { interface Runtrial {
trialId: Array<string>; trialId: Array<string>;
trialTime: Array<number>; trialTime: Array<number>;
} }
interface DurationProps {
source: Array<TableObj>;
}
interface DurationState { interface DurationState {
durationSource: {}; durationSource: {};
} }
class Duration extends React.Component<{}, DurationState> { class Duration extends React.Component<DurationProps, DurationState> {
static intervalDuration = 1;
public _isMounted = false; public _isMounted = false;
constructor(props: {}) { constructor(props: DurationProps) {
super(props);
super(props);
this.state = { this.state = {
durationSource: {} durationSource: {}
}; };
} }
getOption = (dataObj: Runtrial) => { getOption = (dataObj: Runtrial) => {
let xAxis = dataObj.trialTime; return {
let yAxis = dataObj.trialId;
let option = {
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: { axisPointer: {
...@@ -50,6 +45,7 @@ class Duration extends React.Component<{}, DurationState> { ...@@ -50,6 +45,7 @@ class Duration extends React.Component<{}, DurationState> {
left: '1%', left: '1%',
right: '4%' right: '4%'
}, },
dataZoom: [{ dataZoom: [{
type: 'slider', type: 'slider',
name: 'trial', name: 'trial',
...@@ -69,65 +65,52 @@ class Duration extends React.Component<{}, DurationState> { ...@@ -69,65 +65,52 @@ class Duration extends React.Component<{}, DurationState> {
yAxis: { yAxis: {
name: 'Trial', name: 'Trial',
type: 'category', type: 'category',
data: yAxis data: dataObj.trialId
}, },
series: [{ series: [{
type: 'bar', type: 'bar',
data: xAxis data: dataObj.trialTime
}] }]
}; };
return option;
} }
drawRunGraph = () => { drawDurationGraph = (trialJobs: Array<TableObj>) => {
axios(`${MANAGER_IP}/trial-jobs`, { const trialId: Array<string> = [];
method: 'GET' const trialTime: Array<number> = [];
}) const trialRun: Array<Runtrial> = [];
.then(res => { Object.keys(trialJobs).map(item => {
if (res.status === 200) { const temp = trialJobs[item];
const trialJobs = res.data; if (temp.status !== 'WAITING') {
const trialId: Array<string> = []; trialId.push(temp.sequenceId);
const trialTime: Array<number> = []; trialTime.push(temp.duration);
const trialRun: Array<Runtrial> = []; }
Object.keys(trialJobs).map(item => { });
if (trialJobs[item].status !== 'WAITING') { trialRun.push({
let duration: number = 0; trialId: trialId,
const end = trialJobs[item].endTime; trialTime: trialTime
const start = trialJobs[item].startTime; });
if (start && end) { if (this._isMounted) {
duration = (end - start) / 1000; this.setState({
} else { durationSource: this.getOption(trialRun[0])
duration = (new Date().getTime() - start) / 1000;
}
trialId.push(trialJobs[item].sequenceId);
trialTime.push(duration);
}
});
trialRun.push({
trialId: trialId,
trialTime: trialTime
});
if (this._isMounted && res.status === 200) {
this.setState({
durationSource: this.getOption(trialRun[0])
});
}
}
}); });
}
} }
componentDidMount() { componentWillReceiveProps(nextProps: DurationProps) {
const trialJobs = nextProps.source;
this.drawDurationGraph(trialJobs);
}
componentDidMount() {
this._isMounted = true; this._isMounted = true;
this.drawRunGraph(); // init: user don't search
Duration.intervalDuration = window.setInterval(this.drawRunGraph, 10000); const {source} = this.props;
this.drawDurationGraph(source);
} }
componentWillUnmount() { componentWillUnmount() {
this._isMounted = false; this._isMounted = false;
window.clearInterval(Duration.intervalDuration);
} }
render() { render() {
...@@ -136,7 +119,7 @@ class Duration extends React.Component<{}, DurationState> { ...@@ -136,7 +119,7 @@ class Duration extends React.Component<{}, DurationState> {
<div> <div>
<ReactEcharts <ReactEcharts
option={durationSource} option={durationSource}
style={{ width: '100%', height: 412, margin: '0 auto' }} style={{ width: '95%', height: 412, margin: '0 auto' }}
theme="my_theme" theme="my_theme"
/> />
</div> </div>
......
import * as React from 'react';
import { Row, Col, Button, Switch } from 'antd';
import { TooltipForIntermediate, TableObj } from '../../static/interface';
import ReactEcharts from 'echarts-for-react';
require('echarts/lib/component/tooltip');
require('echarts/lib/component/title');
interface Intermedia {
name: string; // id
type: string;
data: Array<number | object>; // intermediate data
hyperPara: object; // each trial hyperpara value
}
interface IntermediateState {
interSource: object;
filterSource: Array<TableObj>;
eachIntermediateNum: number; // trial's intermediate number count
isLoadconfirmBtn: boolean;
isFilter: boolean;
}
interface IntermediateProps {
source: Array<TableObj>;
}
class Intermediate extends React.Component<IntermediateProps, IntermediateState> {
static intervalMediate = 1;
public _isMounted = false;
public pointInput: HTMLInputElement | null;
public minValInput: HTMLInputElement | null;
public maxValInput: HTMLInputElement | null;
constructor(props: IntermediateProps) {
super(props);
this.state = {
interSource: {},
filterSource: [],
eachIntermediateNum: 1,
isLoadconfirmBtn: false,
isFilter: false
};
}
initMediate = () => {
const option = {
grid: {
left: '5%',
top: 40,
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
},
yAxis: {
type: 'value',
name: 'Scape'
}
};
if (this._isMounted) {
this.setState(() => ({
interSource: option
}));
}
}
drawIntermediate = (source: Array<TableObj>) => {
if (source.length > 0) {
const trialIntermediate: Array<Intermedia> = [];
Object.keys(source).map(item => {
const temp = source[item];
trialIntermediate.push({
name: temp.id,
data: temp.description.intermediate,
type: 'line',
hyperPara: temp.description.parameters
});
});
// find max intermediate number
trialIntermediate.sort((a, b) => { return (b.data.length - a.data.length); });
const legend: Array<string> = [];
// max length
const length = trialIntermediate[0].data.length;
const xAxis: Array<number> = [];
Object.keys(trialIntermediate).map(item => {
const temp = trialIntermediate[item];
legend.push(temp.name);
});
for (let i = 1; i <= length; i++) {
xAxis.push(i);
}
const option = {
tooltip: {
trigger: 'item',
enterable: true,
position: function (point: Array<number>, data: TooltipForIntermediate) {
if (data.dataIndex < length / 2) {
return [point[0], 80];
} else {
return [point[0] - 300, 80];
}
},
formatter: function (data: TooltipForIntermediate) {
const trialId = data.seriesName;
let obj = {};
const temp = trialIntermediate.find(key => key.name === trialId);
if (temp !== undefined) {
obj = temp.hyperPara;
}
return '<div class="tooldetailAccuracy">' +
'<div>Trial Id: ' + trialId + '</div>' +
'<div>Intermediate: ' + data.data + '</div>' +
'<div>Parameters: ' +
'<pre>' + JSON.stringify(obj, null, 4) + '</pre>' +
'</div>' +
'</div>';
}
},
grid: {
left: '5%',
top: 40,
containLabel: true
},
xAxis: {
type: 'category',
name: 'Scape',
boundaryGap: false,
data: xAxis
},
yAxis: {
type: 'value',
name: 'Intermediate'
},
series: trialIntermediate
};
if (this._isMounted) {
this.setState(() => ({
interSource: option
}));
}
} else {
this.initMediate();
}
}
// confirm btn function [filter data]
filterLines = () => {
if (this._isMounted) {
const filterSource: Array<TableObj> = [];
this.setState({ isLoadconfirmBtn: true }, () => {
const { source } = this.props;
// get input value
const pointVal = this.pointInput !== null ? this.pointInput.value : '';
const minVal = this.minValInput !== null ? this.minValInput.value : '';
const maxVal = this.maxValInput !== null ? this.maxValInput.value : '';
// user not input message
if (pointVal === '' || minVal === '') {
alert('Please input filter message');
} else {
// user not input max value
const position = JSON.parse(pointVal);
const min = JSON.parse(minVal);
if (maxVal === '') {
Object.keys(source).map(item => {
const temp = source[item];
const val = temp.description.intermediate[position - 1];
if (val >= min) {
filterSource.push(temp);
}
});
} else {
const max = JSON.parse(maxVal);
Object.keys(source).map(item => {
const temp = source[item];
const val = temp.description.intermediate[position - 1];
if (val >= min && val <= max) {
filterSource.push(temp);
}
});
}
if (this._isMounted) {
this.setState({ filterSource: filterSource });
}
this.drawIntermediate(filterSource);
}
this.setState({ isLoadconfirmBtn: false });
});
}
}
switchTurn = (checked: boolean) => {
if (this._isMounted) {
this.setState({ isFilter: checked });
}
if (checked === false) {
this.drawIntermediate(this.props.source);
}
}
componentDidMount() {
this._isMounted = true;
const { source } = this.props;
this.drawIntermediate(source);
}
componentWillReceiveProps(nextProps: IntermediateProps) {
const { isFilter, filterSource } = this.state;
if (isFilter === true) {
const pointVal = this.pointInput !== null ? this.pointInput.value : '';
const minVal = this.minValInput !== null ? this.minValInput.value : '';
if (pointVal === '' && minVal === '') {
this.drawIntermediate(nextProps.source);
} else {
this.drawIntermediate(filterSource);
}
} else {
this.drawIntermediate(nextProps.source);
}
}
componentWillUnmount() {
this._isMounted = false;
}
render() {
const { interSource, isLoadconfirmBtn, isFilter } = this.state;
return (
<div>
{/* style in para.scss */}
<Row className="meline intermediate">
<Col span={8} />
<Col span={3} style={{ height: 34 }}>
{/* filter message */}
<span>filter</span>
<Switch
defaultChecked={false}
onChange={this.switchTurn}
/>
</Col>
{
isFilter
?
<div>
<Col span={3}>
<span>Scape</span>
<input
placeholder="point"
ref={input => this.pointInput = input}
className="strange"
/>
</Col>
<Col className="range" span={10}>
<span>Intermediate Result</span>
<input
placeholder="number"
ref={input => this.minValInput = input}
/>
<span className="heng">-</span>
<input
placeholder="number"
ref={input => this.maxValInput = input}
/>
<Button
type="primary"
className="changeBtu tableButton"
onClick={this.filterLines}
disabled={isLoadconfirmBtn}
>
Confirm
</Button>
</Col>
</div>
:
<Col />
}
</Row>
<Row>
<ReactEcharts
option={interSource}
style={{ width: '100%', height: 418, margin: '0 auto' }}
notMerge={true} // update now
/>
</Row>
</div>
);
}
}
export default Intermediate;
\ No newline at end of file
import * as React from 'react'; import * as React from 'react';
import axios from 'axios';
import { MANAGER_IP } from '../../static/const';
import ReactEcharts from 'echarts-for-react'; import ReactEcharts from 'echarts-for-react';
import { Row, Col, Select, Button, message } from 'antd'; import { Row, Col, Select, Button, message } from 'antd';
import { ParaObj, VisualMapValue, Dimobj } from '../../static/interface'; import { ParaObj, Dimobj, TableObj, SearchSpace } from '../../static/interface';
import { getFinalResult } from '../../static/function';
const Option = Select.Option; const Option = Select.Option;
require('echarts/lib/chart/parallel'); require('echarts/lib/chart/parallel');
require('echarts/lib/component/tooltip'); require('echarts/lib/component/tooltip');
...@@ -20,12 +17,14 @@ interface ParaState { ...@@ -20,12 +17,14 @@ interface ParaState {
swapAxisArr: Array<string>; swapAxisArr: Array<string>;
percent: number; percent: number;
paraNodata: string; paraNodata: string;
visualValue: VisualMapValue; barColorMax: number;
barColorMin: number;
} }
interface SearchSpace { interface ParaProps {
_value: Array<number | string>; dataSource: Array<TableObj>;
_type: string; expSearchSpace: string;
defaultMetric: Array<number> | undefined;
} }
message.config({ message.config({
...@@ -33,12 +32,18 @@ message.config({ ...@@ -33,12 +32,18 @@ message.config({
duration: 2, duration: 2,
}); });
class Para extends React.Component<{}, ParaState> { class Para extends React.Component<ParaProps, ParaState> {
static intervalIDPara = 4;
public _isMounted = false; public _isMounted = false;
constructor(props: {}) { private chartMulineStyle = {
width: '100%',
height: 392,
margin: '0 auto',
padding: '0 15 10 15'
};
constructor(props: ParaProps) {
super(props); super(props);
this.state = { this.state = {
option: {}, option: {},
...@@ -53,28 +58,37 @@ class Para extends React.Component<{}, ParaState> { ...@@ -53,28 +58,37 @@ class Para extends React.Component<{}, ParaState> {
swapAxisArr: [], swapAxisArr: [],
percent: 0, percent: 0,
paraNodata: '', paraNodata: '',
visualValue: { barColorMax: this.props.defaultMetric !== undefined
minAccuracy: 0, ?
maxAccuracy: 1 this.props.defaultMetric[1]
} :
1,
barColorMin: this.props.defaultMetric !== undefined
?
this.props.defaultMetric[0]
:
1
}; };
} }
componentDidMount() {
this._isMounted = true;
this.reInit();
}
getParallelAxis = getParallelAxis =
( (
dimName: Array<string>, searchRange: SearchSpace, dimName: Array<string>, searchRange: SearchSpace,
parallelAxis: Array<Dimobj>, accPara: Array<number>, accPara: Array<number>,
eachTrialParams: Array<string>, paraYdata: number[][] eachTrialParams: Array<string>, paraYdata: number[][]
) => { ) => {
if (this._isMounted) { if (this._isMounted) {
this.setState(() => ({ this.setState(() => ({
dimName: dimName, dimName: dimName
visualValue: {
minAccuracy: accPara.length !== 0 ? Math.min(...accPara) : 0,
maxAccuracy: accPara.length !== 0 ? Math.max(...accPara) : 1
}
})); }));
} }
const parallelAxis: Array<Dimobj> = [];
// search space range and specific value [only number] // search space range and specific value [only number]
for (let i = 0; i < dimName.length; i++) { for (let i = 0; i < dimName.length; i++) {
const searchKey = searchRange[dimName[i]]; const searchKey = searchRange[dimName[i]];
...@@ -107,7 +121,24 @@ class Para extends React.Component<{}, ParaState> { ...@@ -107,7 +121,24 @@ class Para extends React.Component<{}, ParaState> {
dim: i, dim: i,
name: dimName[i], name: dimName[i],
type: 'category', type: 'category',
data: data data: data,
boundaryGap: true,
axisLine: {
lineStyle: {
type: 'dotted', // axis type,solid,dashed,dotted
width: 1
}
},
axisTick: {
show: true,
interval: 0,
alignWithLabel: true,
},
axisLabel: {
show: true,
interval: 0,
// rotate: 30
},
}); });
break; break;
// support log distribute // support log distribute
...@@ -143,100 +174,70 @@ class Para extends React.Component<{}, ParaState> { ...@@ -143,100 +174,70 @@ class Para extends React.Component<{}, ParaState> {
} }
paraYdata.push(temp); paraYdata.push(temp);
}); });
// add acc
Object.keys(paraYdata).map(item => {
paraYdata[item].push(accPara[item]);
});
// according acc to sort ydata
if (paraYdata.length !== 0) {
const len = paraYdata[0].length - 1;
paraYdata.sort((a, b) => b[len] - a[len]);
}
const paraData = {
parallelAxis: parallelAxis,
data: paraYdata
};
const { percent, swapAxisArr } = this.state;
// need to cut down the data
if (percent !== 0) {
const linesNum = paraData.data.length;
const len = Math.floor(linesNum * percent);
paraData.data.length = len;
}
// need to swap the yAxis
if (swapAxisArr.length >= 2) {
this.swapGraph(paraData, swapAxisArr);
}
this.getOption(paraData);
} }
hyperParaPic = () => { hyperParaPic = (dataSource: Array<TableObj>, searchSpace: string) => {
axios const accPara: Array<number> = [];
.all([ // specific value array
axios.get(`${MANAGER_IP}/trial-jobs`), const eachTrialParams: Array<string> = [];
axios.get(`${MANAGER_IP}/experiment`) const paraYdata: number[][] = [];
]) // experiment interface search space obj
.then(axios.spread((res, res1) => { const searchRange = JSON.parse(searchSpace);
if (res.status === 200 && res1.status === 200) { const dimName = Object.keys(searchRange);
if (res.data.length !== 0) { // trial-jobs interface list
const accParaData = res.data; Object.keys(dataSource).map(item => {
const accPara: Array<number> = []; const temp = dataSource[item];
// specific value array if (temp.status === 'SUCCEEDED') {
const eachTrialParams: Array<string> = []; accPara.push(temp.acc.default);
const parallelAxis: Array<Dimobj> = []; eachTrialParams.push(temp.description.parameters);
const paraYdata: number[][] = []; }
// experiment interface search space obj });
const searchRange = JSON.parse(res1.data.params.searchSpace); this.getParallelAxis(dimName, searchRange, accPara, eachTrialParams, paraYdata);
const reallySearchKeys = Object.keys(searchRange);
// trial-jobs interface list
Object.keys(accParaData).map(item => {
if (accParaData[item].status === 'SUCCEEDED') {
const finalData = accParaData[item].finalMetricData;
if (finalData && accParaData[item].hyperParameters) {
const result = getFinalResult(finalData);
accPara.push(result);
// get dim and every line specific number
const temp = JSON.parse(accParaData[item].hyperParameters).parameters;
eachTrialParams.push(temp);
}
}
});
const dimName = reallySearchKeys;
this.getParallelAxis(dimName, searchRange, parallelAxis, accPara, eachTrialParams, paraYdata);
// add acc
Object.keys(paraYdata).map(item => {
paraYdata[item].push(accPara[item]);
});
// according acc to sort ydata
if (paraYdata.length !== 0) {
const len = paraYdata[0].length - 1;
paraYdata.sort((a, b) => b[len] - a[len]);
}
if (this._isMounted) {
this.setState(() => ({
paraBack: {
parallelAxis: parallelAxis,
data: paraYdata
}
}));
}
const { percent, swapAxisArr, paraBack } = this.state;
// need to cut down the data
if (percent !== 0) {
const linesNum = paraBack.data.length;
const len = Math.floor(linesNum * percent);
paraBack.data.length = len;
}
// need to swap the yAxis
if (swapAxisArr.length >= 2) {
this.swapGraph(paraBack, swapAxisArr);
}
this.getOption(paraBack);
}
}
}));
} }
// get percent value number // get percent value number
percentNum = (value: string) => { percentNum = (value: string) => {
window.clearInterval(Para.intervalIDPara);
let vals = parseFloat(value); let vals = parseFloat(value);
if (this._isMounted) { if (this._isMounted) {
this.setState(() => ({ this.setState({ percent: vals }, () => {
percent: vals this.reInit();
})); });
} }
this.hyperParaPic();
Para.intervalIDPara = window.setInterval(this.hyperParaPic, 10000);
} }
// deal with response data into pic data // deal with response data into pic data
getOption = (dataObj: ParaObj) => { getOption = (dataObj: ParaObj) => {
const { visualValue } = this.state; const {barColorMax, barColorMin} = this.state;
let parallelAxis = dataObj.parallelAxis; let parallelAxis = dataObj.parallelAxis;
let paralleData = dataObj.data; let paralleData = dataObj.data;
const maxAccuracy = visualValue.maxAccuracy;
const minAccuracy = visualValue.minAccuracy;
let visualMapObj = {}; let visualMapObj = {};
if (maxAccuracy === minAccuracy) { if (barColorMax === barColorMin) {
visualMapObj = { visualMapObj = {
type: 'continuous', type: 'continuous',
precision: 3, precision: 3,
...@@ -247,10 +248,9 @@ class Para extends React.Component<{}, ParaState> { ...@@ -247,10 +248,9 @@ class Para extends React.Component<{}, ParaState> {
bottom: '20px', bottom: '20px',
type: 'continuous', type: 'continuous',
precision: 3, precision: 3,
min: visualValue.minAccuracy, min: barColorMin,
max: visualValue.maxAccuracy, max: barColorMax,
color: ['#CA0000', '#FFC400', '#90EE90'], color: ['#CA0000', '#FFC400', '#90EE90']
calculable: true
}; };
} }
let optionown = { let optionown = {
...@@ -317,11 +317,9 @@ class Para extends React.Component<{}, ParaState> { ...@@ -317,11 +317,9 @@ class Para extends React.Component<{}, ParaState> {
} }
} }
swapBtn = () => { reInit = () => {
const { dataSource, expSearchSpace } = this.props;
window.clearInterval(Para.intervalIDPara); this.hyperParaPic(dataSource, expSearchSpace);
this.hyperParaPic();
Para.intervalIDPara = window.setInterval(this.hyperParaPic, 10000);
} }
sortDimY = (a: Dimobj, b: Dimobj) => { sortDimY = (a: Dimobj, b: Dimobj) => {
...@@ -330,79 +328,73 @@ class Para extends React.Component<{}, ParaState> { ...@@ -330,79 +328,73 @@ class Para extends React.Component<{}, ParaState> {
// deal with after swap data into pic // deal with after swap data into pic
swapGraph = (paraBack: ParaObj, swapAxisArr: string[]) => { swapGraph = (paraBack: ParaObj, swapAxisArr: string[]) => {
const paralDim = paraBack.parallelAxis;
if (swapAxisArr.length >= 2) { const paraData = paraBack.data;
const paralDim = paraBack.parallelAxis; let temp: number;
const paraData = paraBack.data; let dim1: number;
let temp: number; let dim2: number;
let dim1: number; let bool1: boolean = false;
let dim2: number; let bool2: boolean = false;
let bool1: boolean = false; let bool3: boolean = false;
let bool2: boolean = false; Object.keys(paralDim).map(item => {
let bool3: boolean = false; const paral = paralDim[item];
Object.keys(paralDim).map(item => { switch (paral.name) {
const paral = paralDim[item]; case swapAxisArr[0]:
switch (paral.name) { dim1 = paral.dim;
case swapAxisArr[0]: bool1 = true;
dim1 = paral.dim; break;
bool1 = true;
break; case swapAxisArr[1]:
dim2 = paral.dim;
case swapAxisArr[1]: bool2 = true;
dim2 = paral.dim; break;
bool2 = true;
break; default:
}
default: if (bool1 && bool2) {
} bool3 = true;
if (bool1 && bool2) { }
bool3 = true; });
// swap dim's number
Object.keys(paralDim).map(item => {
if (bool3) {
if (paralDim[item].name === swapAxisArr[0]) {
paralDim[item].dim = dim2;
} }
}); if (paralDim[item].name === swapAxisArr[1]) {
// swap dim's number paralDim[item].dim = dim1;
Object.keys(paralDim).map(item => {
if (bool3) {
if (paralDim[item].name === this.state.swapAxisArr[0]) {
paralDim[item].dim = dim2;
}
if (paralDim[item].name === this.state.swapAxisArr[1]) {
paralDim[item].dim = dim1;
}
} }
}); }
paralDim.sort(this.sortDimY); });
// swap data array paralDim.sort(this.sortDimY);
Object.keys(paraData).map(paraItem => { // swap data array
Object.keys(paraData).map(paraItem => {
temp = paraData[paraItem][dim1];
paraData[paraItem][dim1] = paraData[paraItem][dim2]; temp = paraData[paraItem][dim1];
paraData[paraItem][dim2] = temp; paraData[paraItem][dim1] = paraData[paraItem][dim2];
}); paraData[paraItem][dim2] = temp;
} });
} }
componentDidMount() { componentWillReceiveProps(nextProps: ParaProps) {
const dataSource = nextProps.dataSource;
const expSearchSpace = nextProps.expSearchSpace;
const metricMax = nextProps.defaultMetric !== undefined
?
nextProps.defaultMetric[1]
:
1;
this.setState({ barColorMax: metricMax });
this.hyperParaPic(dataSource, expSearchSpace);
this._isMounted = true;
// default draw all data pic
this.hyperParaPic();
Para.intervalIDPara = window.setInterval(this.hyperParaPic, 10000);
} }
componentWillUnmount() { componentWillUnmount() {
this._isMounted = false; this._isMounted = false;
window.clearInterval(Para.intervalIDPara);
} }
render() { render() {
const { option, paraNodata, dimName } = this.state; const { option, paraNodata, dimName } = this.state;
const chartMulineStyle = {
width: '100%',
height: 392,
margin: '0 auto',
padding: '0 15 10 15'
};
return ( return (
<Row className="parameter"> <Row className="parameter">
<Row> <Row>
...@@ -439,7 +431,7 @@ class Para extends React.Component<{}, ParaState> { ...@@ -439,7 +431,7 @@ class Para extends React.Component<{}, ParaState> {
<Button <Button
type="primary" type="primary"
className="changeBtu tableButton" className="changeBtu tableButton"
onClick={this.swapBtn} onClick={this.reInit}
> >
Confirm Confirm
</Button> </Button>
...@@ -449,8 +441,8 @@ class Para extends React.Component<{}, ParaState> { ...@@ -449,8 +441,8 @@ class Para extends React.Component<{}, ParaState> {
<Row className="searcHyper"> <Row className="searcHyper">
<ReactEcharts <ReactEcharts
option={option} option={option}
style={chartMulineStyle} style={this.chartMulineStyle}
// lazyUpdate={true} lazyUpdate={true}
notMerge={true} // update now notMerge={true} // update now
/> />
<div className="noneData">{paraNodata}</div> <div className="noneData">{paraNodata}</div>
......
...@@ -2,9 +2,8 @@ import * as React from 'react'; ...@@ -2,9 +2,8 @@ import * as React from 'react';
import axios from 'axios'; import axios from 'axios';
import ReactEcharts from 'echarts-for-react'; import ReactEcharts from 'echarts-for-react';
import { import {
Row, Input, Table, Button, Popconfirm, Modal, Checkbox Row, Table, Button, Popconfirm, Modal, Checkbox
} from 'antd'; } from 'antd';
const { TextArea } = Input;
const CheckboxGroup = Checkbox.Group; const CheckboxGroup = Checkbox.Group;
import { MANAGER_IP, DOWNLOAD_IP, trialJobStatus, COLUMN, COLUMN_INDEX } from '../../static/const'; import { MANAGER_IP, DOWNLOAD_IP, trialJobStatus, COLUMN, COLUMN_INDEX } from '../../static/const';
import { convertDuration, intermediateGraphOption, killJob } from '../../static/function'; import { convertDuration, intermediateGraphOption, killJob } from '../../static/function';
...@@ -29,9 +28,7 @@ echarts.registerTheme('my_theme', { ...@@ -29,9 +28,7 @@ echarts.registerTheme('my_theme', {
interface TableListProps { interface TableListProps {
entries: number; entries: number;
tableSource: Array<TableObj>; tableSource: Array<TableObj>;
searchResult: Array<TableObj>;
updateList: Function; updateList: Function;
isHasSearch: boolean;
platform: string; platform: string;
} }
...@@ -78,6 +75,7 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -78,6 +75,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
.then(res => { .then(res => {
if (res.status === 200) { if (res.status === 200) {
const intermediateArr: number[] = []; const intermediateArr: number[] = [];
// support intermediate result is dict
Object.keys(res.data).map(item => { Object.keys(res.data).map(item => {
const temp = JSON.parse(res.data[item].data); const temp = JSON.parse(res.data[item].data);
if (typeof temp === 'object') { if (typeof temp === 'object') {
...@@ -244,10 +242,8 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -244,10 +242,8 @@ class TableList extends React.Component<TableListProps, TableListState> {
render() { render() {
const { entries, tableSource, searchResult, isHasSearch, updateList } = this.props; const { entries, tableSource, updateList } = this.props;
const { intermediateOption, modalVisible, isShowColumn, columnSelected, const { intermediateOption, modalVisible, isShowColumn, columnSelected} = this.state;
logMessage, logModal
} = this.state;
let showTitle = COLUMN; let showTitle = COLUMN;
let bgColor = ''; let bgColor = '';
const trialJob: Array<TrialJob> = []; const trialJob: Array<TrialJob> = [];
...@@ -340,7 +336,10 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -340,7 +336,10 @@ class TableList extends React.Component<TableListProps, TableListState> {
); );
}, },
filters: trialJob, filters: trialJob,
onFilter: (value: string, record: TableObj) => record.status.indexOf(value) === 0, onFilter: (value: string, record: TableObj) => {
return record.status.indexOf(value) === 0;
},
// onFilter: (value: string, record: TableObj) => record.status.indexOf(value) === 0,
sorter: (a: TableObj, b: TableObj): number => a.status.localeCompare(b.status) sorter: (a: TableObj, b: TableObj): number => a.status.localeCompare(b.status)
}); });
break; break;
...@@ -453,7 +452,7 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -453,7 +452,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
<Table <Table
columns={showColumn} columns={showColumn}
expandedRowRender={this.openRow} expandedRowRender={this.openRow}
dataSource={isHasSearch ? searchResult : tableSource} dataSource={tableSource}
className="commonTableStyle" className="commonTableStyle"
pagination={{ pageSize: entries }} pagination={{ pageSize: entries }}
/> />
...@@ -475,24 +474,6 @@ class TableList extends React.Component<TableListProps, TableListState> { ...@@ -475,24 +474,6 @@ class TableList extends React.Component<TableListProps, TableListState> {
theme="my_theme" theme="my_theme"
/> />
</Modal> </Modal>
{/* trial log modal */}
<Modal
title="trial log"
visible={logModal}
onCancel={this.hideLogModal}
footer={null}
destroyOnClose={true}
width="80%"
>
<div id="trialLogContent" style={{ height: window.innerHeight * 0.6 }}>
<TextArea
value={logMessage}
disabled={true}
className="logcontent"
/>
</div>
</Modal>
</div> </div>
{/* Add Column Modal */} {/* Add Column Modal */}
<Modal <Modal
......
...@@ -10,6 +10,11 @@ interface TableObj { ...@@ -10,6 +10,11 @@ interface TableObj {
color?: string; color?: string;
} }
interface SearchSpace {
_value: Array<number | string>;
_type: string;
}
interface FinalType { interface FinalType {
default: string; default: string;
} }
...@@ -21,6 +26,7 @@ interface ErrorParameter { ...@@ -21,6 +26,7 @@ interface ErrorParameter {
interface Parameters { interface Parameters {
parameters: ErrorParameter; parameters: ErrorParameter;
logPath?: string; logPath?: string;
intermediate?: Array<number>;
} }
interface Experiment { interface Experiment {
...@@ -54,6 +60,12 @@ interface DetailAccurPoint { ...@@ -54,6 +60,12 @@ interface DetailAccurPoint {
searchSpace: string; searchSpace: string;
} }
interface TooltipForIntermediate {
data: string;
seriesName: string;
dataIndex: number;
}
interface TooltipForAccuracy { interface TooltipForAccuracy {
data: Array<number | object>; data: Array<number | object>;
} }
...@@ -80,6 +92,10 @@ interface Dimobj { ...@@ -80,6 +92,10 @@ interface Dimobj {
min?: number; min?: number;
type?: string; type?: string;
data?: string[]; data?: string[];
boundaryGap?: boolean;
axisTick?: object;
axisLabel?: object;
axisLine?: object;
} }
interface ParaObj { interface ParaObj {
...@@ -87,11 +103,6 @@ interface ParaObj { ...@@ -87,11 +103,6 @@ interface ParaObj {
parallelAxis: Array<Dimobj>; parallelAxis: Array<Dimobj>;
} }
interface VisualMapValue {
maxAccuracy: number;
minAccuracy: number;
}
interface FinalResult { interface FinalResult {
data: string; data: string;
} }
...@@ -100,5 +111,6 @@ export { ...@@ -100,5 +111,6 @@ export {
TableObj, Parameters, Experiment, TableObj, Parameters, Experiment,
AccurPoint, TrialNumber, TrialJob, AccurPoint, TrialNumber, TrialJob,
DetailAccurPoint, TooltipForAccuracy, DetailAccurPoint, TooltipForAccuracy,
ParaObj, VisualMapValue, Dimobj, FinalResult, FinalType ParaObj, Dimobj, FinalResult, FinalType,
TooltipForIntermediate, SearchSpace
}; };
...@@ -13,7 +13,6 @@ $titleBgcolor: #b3b3b3; ...@@ -13,7 +13,6 @@ $titleBgcolor: #b3b3b3;
height: 22px; height: 22px;
margin-top: -8px; margin-top: -8px;
padding-left: 14px; padding-left: 14px;
padding-right: 14px;
} }
span{ span{
...@@ -22,9 +21,22 @@ $titleBgcolor: #b3b3b3; ...@@ -22,9 +21,22 @@ $titleBgcolor: #b3b3b3;
font-family: 'Segoe'; font-family: 'Segoe';
color: #333; color: #333;
line-height: 38px; line-height: 38px;
margin-left: 14px;
}
i{
font-size: 24px;
margin-left: 14px;
color: #545454;
position: relative;
top: 2px;
} }
} }
/* antd icon margin intermediate result style*/
#tabsty .anticon{
margin-right: 0;
}
.top10bg{ .top10bg{
background-color: $titleBgcolor; background-color: $titleBgcolor;
......
.parameter{ .parameter{
height: 100%; height: 100%;
}
.meline{ .meline{
margin-top: 15px; margin-top: 15px;
span{ span{
font-size: 14px; font-size: 14px;
margin-right: 6px; margin-right: 6px;
}
} }
} }
.searcHyper{ .searcHyper{
...@@ -24,4 +23,23 @@ ...@@ -24,4 +23,23 @@
font-size: 13px; font-size: 13px;
color: #999; color: #999;
} }
} }
\ No newline at end of file
/* Intermediate Result Style */
.intermediate{
/* border: 1px solid blue; */
input{
width: 80px;
height: 32px;
padding-left: 8px;
}
.strange{
margin-top: 2px;
}
.range{
.heng{
margin-left: 6px;
margin-right: 6px;
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment