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';
import axios from 'axios';
import { Row, Col } from 'antd';
import { MANAGER_IP } from '../static/const';
import {
Experiment, TableObj,
Parameters, TrialNumber
} from '../static/interface';
import { Experiment, TableObj, Parameters, TrialNumber } from '../static/interface';
import { getFinal } from '../static/function';
import SuccessTable from './overview/SuccessTable';
import Title1 from './overview/Title1';
......@@ -117,7 +114,9 @@ class Overview extends React.Component<{}, OverviewState> {
clusterMetaData: clusterMetaData ? clusterMetaData : undefined
});
// 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 => {
const key = searchSpace[item]._type;
let value = searchSpace[item]._value;
......
......@@ -141,6 +141,7 @@ class SlideBar extends React.Component<{}, SliderState> {
}
});
}
getNNIversion = () => {
axios(`${MANAGER_IP}/version`, {
method: 'GET'
......@@ -233,7 +234,6 @@ class SlideBar extends React.Component<{}, SliderState> {
</a>
<span className="version">Version: {version}</span>
</Col>
</Row>
);
}
......
This diff is collapsed.
......@@ -2,7 +2,7 @@ import * as React from 'react';
interface Title1Props {
text: string;
icon: string;
icon?: 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 axios from 'axios';
import { MANAGER_IP } from '../../static/const';
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/component/tooltip');
require('echarts/lib/component/title');
echarts.registerTheme('my_theme', {
color: '#3c8dbc'
});
interface Runtrial {
trialId: Array<string>;
trialTime: Array<number>;
}
interface DurationProps {
source: Array<TableObj>;
}
interface DurationState {
durationSource: {};
}
class Duration extends React.Component<{}, DurationState> {
class Duration extends React.Component<DurationProps, DurationState> {
static intervalDuration = 1;
public _isMounted = false;
constructor(props: {}) {
super(props);
constructor(props: DurationProps) {
super(props);
this.state = {
durationSource: {}
};
}
getOption = (dataObj: Runtrial) => {
let xAxis = dataObj.trialTime;
let yAxis = dataObj.trialId;
let option = {
return {
tooltip: {
trigger: 'axis',
axisPointer: {
......@@ -50,6 +45,7 @@ class Duration extends React.Component<{}, DurationState> {
left: '1%',
right: '4%'
},
dataZoom: [{
type: 'slider',
name: 'trial',
......@@ -69,65 +65,52 @@ class Duration extends React.Component<{}, DurationState> {
yAxis: {
name: 'Trial',
type: 'category',
data: yAxis
data: dataObj.trialId
},
series: [{
type: 'bar',
data: xAxis
data: dataObj.trialTime
}]
};
return option;
}
drawRunGraph = () => {
axios(`${MANAGER_IP}/trial-jobs`, {
method: 'GET'
})
.then(res => {
if (res.status === 200) {
const trialJobs = res.data;
const trialId: Array<string> = [];
const trialTime: Array<number> = [];
const trialRun: Array<Runtrial> = [];
Object.keys(trialJobs).map(item => {
if (trialJobs[item].status !== 'WAITING') {
let duration: number = 0;
const end = trialJobs[item].endTime;
const start = trialJobs[item].startTime;
if (start && end) {
duration = (end - start) / 1000;
} else {
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])
});
}
}
drawDurationGraph = (trialJobs: Array<TableObj>) => {
const trialId: Array<string> = [];
const trialTime: Array<number> = [];
const trialRun: Array<Runtrial> = [];
Object.keys(trialJobs).map(item => {
const temp = trialJobs[item];
if (temp.status !== 'WAITING') {
trialId.push(temp.sequenceId);
trialTime.push(temp.duration);
}
});
trialRun.push({
trialId: trialId,
trialTime: trialTime
});
if (this._isMounted) {
this.setState({
durationSource: this.getOption(trialRun[0])
});
}
}
componentDidMount() {
componentWillReceiveProps(nextProps: DurationProps) {
const trialJobs = nextProps.source;
this.drawDurationGraph(trialJobs);
}
componentDidMount() {
this._isMounted = true;
this.drawRunGraph();
Duration.intervalDuration = window.setInterval(this.drawRunGraph, 10000);
// init: user don't search
const {source} = this.props;
this.drawDurationGraph(source);
}
componentWillUnmount() {
this._isMounted = false;
window.clearInterval(Duration.intervalDuration);
}
render() {
......@@ -136,7 +119,7 @@ class Duration extends React.Component<{}, DurationState> {
<div>
<ReactEcharts
option={durationSource}
style={{ width: '100%', height: 412, margin: '0 auto' }}
style={{ width: '95%', height: 412, margin: '0 auto' }}
theme="my_theme"
/>
</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 axios from 'axios';
import { MANAGER_IP } from '../../static/const';
import ReactEcharts from 'echarts-for-react';
import { Row, Col, Select, Button, message } from 'antd';
import { ParaObj, VisualMapValue, Dimobj } from '../../static/interface';
import { getFinalResult } from '../../static/function';
import { ParaObj, Dimobj, TableObj, SearchSpace } from '../../static/interface';
const Option = Select.Option;
require('echarts/lib/chart/parallel');
require('echarts/lib/component/tooltip');
......@@ -20,12 +17,14 @@ interface ParaState {
swapAxisArr: Array<string>;
percent: number;
paraNodata: string;
visualValue: VisualMapValue;
barColorMax: number;
barColorMin: number;
}
interface SearchSpace {
_value: Array<number | string>;
_type: string;
interface ParaProps {
dataSource: Array<TableObj>;
expSearchSpace: string;
defaultMetric: Array<number> | undefined;
}
message.config({
......@@ -33,12 +32,18 @@ message.config({
duration: 2,
});
class Para extends React.Component<{}, ParaState> {
class Para extends React.Component<ParaProps, ParaState> {
static intervalIDPara = 4;
public _isMounted = false;
constructor(props: {}) {
private chartMulineStyle = {
width: '100%',
height: 392,
margin: '0 auto',
padding: '0 15 10 15'
};
constructor(props: ParaProps) {
super(props);
this.state = {
option: {},
......@@ -53,28 +58,37 @@ class Para extends React.Component<{}, ParaState> {
swapAxisArr: [],
percent: 0,
paraNodata: '',
visualValue: {
minAccuracy: 0,
maxAccuracy: 1
}
barColorMax: this.props.defaultMetric !== undefined
?
this.props.defaultMetric[1]
:
1,
barColorMin: this.props.defaultMetric !== undefined
?
this.props.defaultMetric[0]
:
1
};
}
componentDidMount() {
this._isMounted = true;
this.reInit();
}
getParallelAxis =
(
dimName: Array<string>, searchRange: SearchSpace,
parallelAxis: Array<Dimobj>, accPara: Array<number>,
accPara: Array<number>,
eachTrialParams: Array<string>, paraYdata: number[][]
) => {
if (this._isMounted) {
this.setState(() => ({
dimName: dimName,
visualValue: {
minAccuracy: accPara.length !== 0 ? Math.min(...accPara) : 0,
maxAccuracy: accPara.length !== 0 ? Math.max(...accPara) : 1
}
dimName: dimName
}));
}
const parallelAxis: Array<Dimobj> = [];
// search space range and specific value [only number]
for (let i = 0; i < dimName.length; i++) {
const searchKey = searchRange[dimName[i]];
......@@ -107,7 +121,24 @@ class Para extends React.Component<{}, ParaState> {
dim: i,
name: dimName[i],
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;
// support log distribute
......@@ -143,100 +174,70 @@ class Para extends React.Component<{}, ParaState> {
}
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 = () => {
axios
.all([
axios.get(`${MANAGER_IP}/trial-jobs`),
axios.get(`${MANAGER_IP}/experiment`)
])
.then(axios.spread((res, res1) => {
if (res.status === 200 && res1.status === 200) {
if (res.data.length !== 0) {
const accParaData = res.data;
const accPara: Array<number> = [];
// specific value array
const eachTrialParams: Array<string> = [];
const parallelAxis: Array<Dimobj> = [];
const paraYdata: number[][] = [];
// experiment interface search space obj
const searchRange = JSON.parse(res1.data.params.searchSpace);
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);
}
}
}));
hyperParaPic = (dataSource: Array<TableObj>, searchSpace: string) => {
const accPara: Array<number> = [];
// specific value array
const eachTrialParams: Array<string> = [];
const paraYdata: number[][] = [];
// experiment interface search space obj
const searchRange = JSON.parse(searchSpace);
const dimName = Object.keys(searchRange);
// trial-jobs interface list
Object.keys(dataSource).map(item => {
const temp = dataSource[item];
if (temp.status === 'SUCCEEDED') {
accPara.push(temp.acc.default);
eachTrialParams.push(temp.description.parameters);
}
});
this.getParallelAxis(dimName, searchRange, accPara, eachTrialParams, paraYdata);
}
// get percent value number
percentNum = (value: string) => {
window.clearInterval(Para.intervalIDPara);
let vals = parseFloat(value);
if (this._isMounted) {
this.setState(() => ({
percent: vals
}));
this.setState({ percent: vals }, () => {
this.reInit();
});
}
this.hyperParaPic();
Para.intervalIDPara = window.setInterval(this.hyperParaPic, 10000);
}
// deal with response data into pic data
getOption = (dataObj: ParaObj) => {
const { visualValue } = this.state;
const {barColorMax, barColorMin} = this.state;
let parallelAxis = dataObj.parallelAxis;
let paralleData = dataObj.data;
const maxAccuracy = visualValue.maxAccuracy;
const minAccuracy = visualValue.minAccuracy;
let visualMapObj = {};
if (maxAccuracy === minAccuracy) {
if (barColorMax === barColorMin) {
visualMapObj = {
type: 'continuous',
precision: 3,
......@@ -247,10 +248,9 @@ class Para extends React.Component<{}, ParaState> {
bottom: '20px',
type: 'continuous',
precision: 3,
min: visualValue.minAccuracy,
max: visualValue.maxAccuracy,
color: ['#CA0000', '#FFC400', '#90EE90'],
calculable: true
min: barColorMin,
max: barColorMax,
color: ['#CA0000', '#FFC400', '#90EE90']
};
}
let optionown = {
......@@ -317,11 +317,9 @@ class Para extends React.Component<{}, ParaState> {
}
}
swapBtn = () => {
window.clearInterval(Para.intervalIDPara);
this.hyperParaPic();
Para.intervalIDPara = window.setInterval(this.hyperParaPic, 10000);
reInit = () => {
const { dataSource, expSearchSpace } = this.props;
this.hyperParaPic(dataSource, expSearchSpace);
}
sortDimY = (a: Dimobj, b: Dimobj) => {
......@@ -330,79 +328,73 @@ class Para extends React.Component<{}, ParaState> {
// deal with after swap data into pic
swapGraph = (paraBack: ParaObj, swapAxisArr: string[]) => {
if (swapAxisArr.length >= 2) {
const paralDim = paraBack.parallelAxis;
const paraData = paraBack.data;
let temp: number;
let dim1: number;
let dim2: number;
let bool1: boolean = false;
let bool2: boolean = false;
let bool3: boolean = false;
Object.keys(paralDim).map(item => {
const paral = paralDim[item];
switch (paral.name) {
case swapAxisArr[0]:
dim1 = paral.dim;
bool1 = true;
break;
case swapAxisArr[1]:
dim2 = paral.dim;
bool2 = true;
break;
default:
}
if (bool1 && bool2) {
bool3 = true;
const paralDim = paraBack.parallelAxis;
const paraData = paraBack.data;
let temp: number;
let dim1: number;
let dim2: number;
let bool1: boolean = false;
let bool2: boolean = false;
let bool3: boolean = false;
Object.keys(paralDim).map(item => {
const paral = paralDim[item];
switch (paral.name) {
case swapAxisArr[0]:
dim1 = paral.dim;
bool1 = true;
break;
case swapAxisArr[1]:
dim2 = paral.dim;
bool2 = true;
break;
default:
}
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;
}
});
// swap dim's number
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;
}
if (paralDim[item].name === swapAxisArr[1]) {
paralDim[item].dim = dim1;
}
});
paralDim.sort(this.sortDimY);
// swap data array
Object.keys(paraData).map(paraItem => {
temp = paraData[paraItem][dim1];
paraData[paraItem][dim1] = paraData[paraItem][dim2];
paraData[paraItem][dim2] = temp;
});
}
}
});
paralDim.sort(this.sortDimY);
// swap data array
Object.keys(paraData).map(paraItem => {
temp = paraData[paraItem][dim1];
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() {
this._isMounted = false;
window.clearInterval(Para.intervalIDPara);
}
render() {
const { option, paraNodata, dimName } = this.state;
const chartMulineStyle = {
width: '100%',
height: 392,
margin: '0 auto',
padding: '0 15 10 15'
};
return (
<Row className="parameter">
<Row>
......@@ -439,7 +431,7 @@ class Para extends React.Component<{}, ParaState> {
<Button
type="primary"
className="changeBtu tableButton"
onClick={this.swapBtn}
onClick={this.reInit}
>
Confirm
</Button>
......@@ -449,8 +441,8 @@ class Para extends React.Component<{}, ParaState> {
<Row className="searcHyper">
<ReactEcharts
option={option}
style={chartMulineStyle}
// lazyUpdate={true}
style={this.chartMulineStyle}
lazyUpdate={true}
notMerge={true} // update now
/>
<div className="noneData">{paraNodata}</div>
......
......@@ -2,9 +2,8 @@ import * as React from 'react';
import axios from 'axios';
import ReactEcharts from 'echarts-for-react';
import {
Row, Input, Table, Button, Popconfirm, Modal, Checkbox
Row, Table, Button, Popconfirm, Modal, Checkbox
} from 'antd';
const { TextArea } = Input;
const CheckboxGroup = Checkbox.Group;
import { MANAGER_IP, DOWNLOAD_IP, trialJobStatus, COLUMN, COLUMN_INDEX } from '../../static/const';
import { convertDuration, intermediateGraphOption, killJob } from '../../static/function';
......@@ -29,9 +28,7 @@ echarts.registerTheme('my_theme', {
interface TableListProps {
entries: number;
tableSource: Array<TableObj>;
searchResult: Array<TableObj>;
updateList: Function;
isHasSearch: boolean;
platform: string;
}
......@@ -78,6 +75,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
.then(res => {
if (res.status === 200) {
const intermediateArr: number[] = [];
// support intermediate result is dict
Object.keys(res.data).map(item => {
const temp = JSON.parse(res.data[item].data);
if (typeof temp === 'object') {
......@@ -244,10 +242,8 @@ class TableList extends React.Component<TableListProps, TableListState> {
render() {
const { entries, tableSource, searchResult, isHasSearch, updateList } = this.props;
const { intermediateOption, modalVisible, isShowColumn, columnSelected,
logMessage, logModal
} = this.state;
const { entries, tableSource, updateList } = this.props;
const { intermediateOption, modalVisible, isShowColumn, columnSelected} = this.state;
let showTitle = COLUMN;
let bgColor = '';
const trialJob: Array<TrialJob> = [];
......@@ -340,7 +336,10 @@ class TableList extends React.Component<TableListProps, TableListState> {
);
},
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)
});
break;
......@@ -453,7 +452,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
<Table
columns={showColumn}
expandedRowRender={this.openRow}
dataSource={isHasSearch ? searchResult : tableSource}
dataSource={tableSource}
className="commonTableStyle"
pagination={{ pageSize: entries }}
/>
......@@ -475,24 +474,6 @@ class TableList extends React.Component<TableListProps, TableListState> {
theme="my_theme"
/>
</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>
{/* Add Column Modal */}
<Modal
......
......@@ -10,6 +10,11 @@ interface TableObj {
color?: string;
}
interface SearchSpace {
_value: Array<number | string>;
_type: string;
}
interface FinalType {
default: string;
}
......@@ -21,6 +26,7 @@ interface ErrorParameter {
interface Parameters {
parameters: ErrorParameter;
logPath?: string;
intermediate?: Array<number>;
}
interface Experiment {
......@@ -54,6 +60,12 @@ interface DetailAccurPoint {
searchSpace: string;
}
interface TooltipForIntermediate {
data: string;
seriesName: string;
dataIndex: number;
}
interface TooltipForAccuracy {
data: Array<number | object>;
}
......@@ -80,6 +92,10 @@ interface Dimobj {
min?: number;
type?: string;
data?: string[];
boundaryGap?: boolean;
axisTick?: object;
axisLabel?: object;
axisLine?: object;
}
interface ParaObj {
......@@ -87,11 +103,6 @@ interface ParaObj {
parallelAxis: Array<Dimobj>;
}
interface VisualMapValue {
maxAccuracy: number;
minAccuracy: number;
}
interface FinalResult {
data: string;
}
......@@ -100,5 +111,6 @@ export {
TableObj, Parameters, Experiment,
AccurPoint, TrialNumber, TrialJob,
DetailAccurPoint, TooltipForAccuracy,
ParaObj, VisualMapValue, Dimobj, FinalResult, FinalType
ParaObj, Dimobj, FinalResult, FinalType,
TooltipForIntermediate, SearchSpace
};
......@@ -13,7 +13,6 @@ $titleBgcolor: #b3b3b3;
height: 22px;
margin-top: -8px;
padding-left: 14px;
padding-right: 14px;
}
span{
......@@ -22,9 +21,22 @@ $titleBgcolor: #b3b3b3;
font-family: 'Segoe';
color: #333;
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{
background-color: $titleBgcolor;
......
.parameter{
height: 100%;
height: 100%;
}
.meline{
margin-top: 15px;
.meline{
margin-top: 15px;
span{
font-size: 14px;
margin-right: 6px;
}
span{
font-size: 14px;
margin-right: 6px;
}
}
.searcHyper{
......@@ -24,4 +23,23 @@
font-size: 13px;
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