"docs/en_US/Tutorial/AnnotationSpec.md" did not exist on "14c1b31c784e14a498e78631bb7f40f0ca3a9151"
Commit a03570a0 authored by Lijiao's avatar Lijiao Committed by liuzhe-lz
Browse files

add dataZoom for graph (#1736)

* add dataZoom for graph

* fix comments- datazoom Y

* fix bug of val bold

* update yarn.lock
parent d07f7280
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
"copy-to-clipboard": "^3.0.8", "copy-to-clipboard": "^3.0.8",
"css-loader": "0.28.7", "css-loader": "0.28.7",
"dotenv": "^8.0.0", "dotenv": "^8.0.0",
"echarts": "^4.1.0", "echarts": "^4.5.0",
"echarts-for-react": "^2.0.14", "echarts-for-react": "^2.0.14",
"file-loader": "^4.1.0", "file-loader": "^4.1.0",
"fork-ts-checker-webpack-plugin": "^1.5.0", "fork-ts-checker-webpack-plugin": "^1.5.0",
......
...@@ -3,7 +3,7 @@ import { Switch } from 'antd'; ...@@ -3,7 +3,7 @@ import { Switch } from 'antd';
import ReactEcharts from 'echarts-for-react'; import ReactEcharts from 'echarts-for-react';
import { EXPERIMENT, TRIALS } from '../../static/datamodel'; import { EXPERIMENT, TRIALS } from '../../static/datamodel';
import { Trial } from '../../static/model/trial'; import { Trial } from '../../static/model/trial';
import { TooltipForAccuracy } from '../../static/interface'; import { TooltipForAccuracy, EventMap } from '../../static/interface';
require('echarts/lib/chart/scatter'); require('echarts/lib/chart/scatter');
require('echarts/lib/component/tooltip'); require('echarts/lib/component/tooltip');
require('echarts/lib/component/title'); require('echarts/lib/component/title');
...@@ -16,12 +16,18 @@ interface DefaultPointProps { ...@@ -16,12 +16,18 @@ interface DefaultPointProps {
interface DefaultPointState { interface DefaultPointState {
bestCurveEnabled: boolean; bestCurveEnabled: boolean;
startY: number; // dataZoomY
endY: number;
} }
class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState> { class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState> {
constructor(props: DefaultPointProps) { constructor(props: DefaultPointProps) {
super(props); super(props);
this.state = { bestCurveEnabled: false }; this.state = {
bestCurveEnabled: false,
startY: 0, // dataZoomY
endY: 100,
};
} }
loadDefault = (checked: boolean) => { loadDefault = (checked: boolean) => {
...@@ -35,6 +41,7 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState> ...@@ -35,6 +41,7 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
render() { render() {
const graph = this.generateGraph(); const graph = this.generateGraph();
const accNodata = (graph === EmptyGraph ? 'No data' : ''); const accNodata = (graph === EmptyGraph ? 'No data' : '');
const onEvents = { 'dataZoom': this.metricDataZoom };
return ( return (
<div> <div>
...@@ -53,6 +60,7 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState> ...@@ -53,6 +60,7 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
}} }}
theme="my_theme" theme="my_theme"
notMerge={true} // update now notMerge={true} // update now
onEvents={onEvents}
/> />
<div className="showMess">{accNodata}</div> <div className="showMess">{accNodata}</div>
</div> </div>
...@@ -64,31 +72,17 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState> ...@@ -64,31 +72,17 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
if (trials.length === 0) { if (trials.length === 0) {
return EmptyGraph; return EmptyGraph;
} }
const graph = generateGraphConfig(trials[trials.length - 1].sequenceId); const graph = this.generateGraphConfig(trials[trials.length - 1].sequenceId);
if (this.state.bestCurveEnabled) { if (this.state.bestCurveEnabled) {
(graph as any).series = [ generateBestCurveSeries(trials), generateScatterSeries(trials) ]; (graph as any).series = [generateBestCurveSeries(trials), generateScatterSeries(trials)];
} else { } else {
(graph as any).series = [ generateScatterSeries(trials) ]; (graph as any).series = [generateScatterSeries(trials)];
} }
return graph; return graph;
} }
}
const EmptyGraph = {
grid: {
left: '8%'
},
xAxis: {
name: 'Trial',
type: 'category',
},
yAxis: {
name: 'Default metric',
type: 'value',
}
};
function generateGraphConfig(maxSequenceId: number) { private generateGraphConfig(maxSequenceId: number) {
const { startY, endY } = this.state;
return { return {
grid: { grid: {
left: '8%', left: '8%',
...@@ -97,7 +91,7 @@ function generateGraphConfig(maxSequenceId: number) { ...@@ -97,7 +91,7 @@ function generateGraphConfig(maxSequenceId: number) {
trigger: 'item', trigger: 'item',
enterable: true, enterable: true,
position: (point: Array<number>, data: TooltipForAccuracy) => ( position: (point: Array<number>, data: TooltipForAccuracy) => (
[ (data.data[0] < maxSequenceId ? point[0] : (point[0] - 300)), 80 ] [(data.data[0] < maxSequenceId ? point[0] : (point[0] - 300)), 80]
), ),
formatter: (data: TooltipForAccuracy) => ( formatter: (data: TooltipForAccuracy) => (
'<div class="tooldetailAccuracy">' + '<div class="tooldetailAccuracy">' +
...@@ -107,6 +101,16 @@ function generateGraphConfig(maxSequenceId: number) { ...@@ -107,6 +101,16 @@ function generateGraphConfig(maxSequenceId: number) {
'</div>' '</div>'
), ),
}, },
dataZoom: [
{
id: 'dataZoomY',
type: 'inside',
yAxisIndex: [0],
filterMode: 'empty',
start: startY,
end: endY
}
],
xAxis: { xAxis: {
name: 'Trial', name: 'Trial',
type: 'category', type: 'category',
...@@ -118,8 +122,33 @@ function generateGraphConfig(maxSequenceId: number) { ...@@ -118,8 +122,33 @@ function generateGraphConfig(maxSequenceId: number) {
}, },
series: undefined, series: undefined,
}; };
}
private metricDataZoom = (e: EventMap) => {
if (e.batch !== undefined) {
this.setState(() => ({
startY: (e.batch[0].start !== null ? e.batch[0].start : 0),
endY: (e.batch[0].end !== null ? e.batch[0].end : 100)
}));
}
}
} }
const EmptyGraph = {
grid: {
left: '8%'
},
xAxis: {
name: 'Trial',
type: 'category',
},
yAxis: {
name: 'Default metric',
type: 'value',
scale: true,
}
};
function generateScatterSeries(trials: Trial[]) { function generateScatterSeries(trials: Trial[]) {
const data = trials.map(trial => [ const data = trials.map(trial => [
trial.sequenceId, trial.sequenceId,
...@@ -135,17 +164,17 @@ function generateScatterSeries(trials: Trial[]) { ...@@ -135,17 +164,17 @@ function generateScatterSeries(trials: Trial[]) {
function generateBestCurveSeries(trials: Trial[]) { function generateBestCurveSeries(trials: Trial[]) {
let best = trials[0]; let best = trials[0];
const data = [[ best.sequenceId, best.accuracy, best.description.parameters ]]; const data = [[best.sequenceId, best.accuracy, best.description.parameters]];
for (let i = 1; i < trials.length; i++) { for (let i = 1; i < trials.length; i++) {
const trial = trials[i]; const trial = trials[i];
const delta = trial.accuracy! - best.accuracy!; const delta = trial.accuracy! - best.accuracy!;
const better = (EXPERIMENT.optimizeMode === 'minimize') ? (delta < 0) : (delta > 0); const better = (EXPERIMENT.optimizeMode === 'minimize') ? (delta < 0) : (delta > 0);
if (better) { if (better) {
data.push([ trial.sequenceId, trial.accuracy, trial.description.parameters ]); data.push([trial.sequenceId, trial.accuracy, trial.description.parameters]);
best = trial; best = trial;
} else { } else {
data.push([ trial.sequenceId, best.accuracy, trial.description.parameters ]); data.push([trial.sequenceId, best.accuracy, trial.description.parameters]);
} }
} }
......
import * as React from 'react'; import * as React from 'react';
import ReactEcharts from 'echarts-for-react'; import ReactEcharts from 'echarts-for-react';
import { TableObj } from 'src/static/interface'; import { TableObj, EventMap } from 'src/static/interface';
import { filterDuration } from 'src/static/function'; import { filterDuration } from 'src/static/function';
require('echarts/lib/chart/bar'); require('echarts/lib/chart/bar');
require('echarts/lib/component/tooltip'); require('echarts/lib/component/tooltip');
...@@ -17,7 +17,8 @@ interface DurationProps { ...@@ -17,7 +17,8 @@ interface DurationProps {
} }
interface DurationState { interface DurationState {
durationSource: {}; startDuration: number; // for record data zoom
endDuration: number;
} }
class Duration extends React.Component<DurationProps, DurationState> { class Duration extends React.Component<DurationProps, DurationState> {
...@@ -26,63 +27,13 @@ class Duration extends React.Component<DurationProps, DurationState> { ...@@ -26,63 +27,13 @@ class Duration extends React.Component<DurationProps, DurationState> {
super(props); super(props);
this.state = { this.state = {
durationSource: this.initDuration(this.props.source), startDuration: 0, // for record data zoom
}; endDuration: 100,
}
initDuration = (source: Array<TableObj>) => {
const trialId: Array<string> = [];
const trialTime: Array<number> = [];
const trialJobs = source.filter(filterDuration);
Object.keys(trialJobs).map(item => {
const temp = trialJobs[item];
trialId.push(temp.sequenceId);
trialTime.push(temp.duration);
});
return {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
bottom: '3%',
containLabel: true,
left: '1%',
right: '4%'
},
dataZoom: [{
type: 'slider',
name: 'trial',
filterMode: 'filter',
yAxisIndex: 0,
orient: 'vertical'
}, {
type: 'slider',
name: 'trial',
filterMode: 'filter',
xAxisIndex: 0
}],
xAxis: {
name: 'Time',
type: 'value',
},
yAxis: {
name: 'Trial',
type: 'category',
data: trialId
},
series: [{
type: 'bar',
data: trialTime
}]
}; };
} }
getOption = (dataObj: Runtrial) => { getOption = (dataObj: Runtrial) => {
const { startDuration, endDuration } = this.state;
return { return {
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
...@@ -96,19 +47,16 @@ class Duration extends React.Component<DurationProps, DurationState> { ...@@ -96,19 +47,16 @@ class Duration extends React.Component<DurationProps, DurationState> {
left: '1%', left: '1%',
right: '4%' right: '4%'
}, },
dataZoom: [
dataZoom: [{ {
type: 'slider', id: 'dataZoomY',
name: 'trial', type: 'inside',
filterMode: 'filter', yAxisIndex: [0],
yAxisIndex: 0, filterMode: 'empty',
orient: 'vertical' start: startDuration,
}, { end: endDuration
type: 'slider', },
name: 'trial', ],
filterMode: 'filter',
xAxisIndex: 0
}],
xAxis: { xAxis: {
name: 'Time', name: 'Time',
type: 'value', type: 'value',
...@@ -140,21 +88,7 @@ class Duration extends React.Component<DurationProps, DurationState> { ...@@ -140,21 +88,7 @@ class Duration extends React.Component<DurationProps, DurationState> {
trialId: trialId, trialId: trialId,
trialTime: trialTime trialTime: trialTime
}); });
this.setState({ return this.getOption(trialRun[0]);
durationSource: this.getOption(trialRun[0])
});
}
componentDidMount() {
const { source } = this.props;
this.drawDurationGraph(source);
}
componentWillReceiveProps(nextProps: DurationProps) {
const { whichGraph, source } = nextProps;
if (whichGraph === '3') {
this.drawDurationGraph(source);
}
} }
shouldComponentUpdate(nextProps: DurationProps, nextState: DurationState) { shouldComponentUpdate(nextProps: DurationProps, nextState: DurationState) {
...@@ -183,18 +117,31 @@ class Duration extends React.Component<DurationProps, DurationState> { ...@@ -183,18 +117,31 @@ class Duration extends React.Component<DurationProps, DurationState> {
} }
render() { render() {
const { durationSource } = this.state;
const { source } = this.props;
const graph = this.drawDurationGraph(source);
const onEvents = { 'dataZoom': this.durationDataZoom };
return ( return (
<div> <div>
<ReactEcharts <ReactEcharts
option={durationSource} option={graph}
style={{ width: '95%', height: 412, margin: '0 auto' }} style={{ width: '95%', height: 412, margin: '0 auto' }}
theme="my_theme" theme="my_theme"
notMerge={true} // update now notMerge={true} // update now
onEvents={onEvents}
/> />
</div> </div>
); );
} }
private durationDataZoom = (e: EventMap) => {
if (e.batch !== undefined) {
this.setState(() => ({
startDuration: (e.batch[0].start !== null ? e.batch[0].start : 0),
endDuration: (e.batch[0].end !== null ? e.batch[0].end : 100)
}));
}
}
} }
export default Duration; export default Duration;
import * as React from 'react'; import * as React from 'react';
import { Row, Button, Switch } from 'antd'; import { Row, Button, Switch } from 'antd';
import { TooltipForIntermediate, TableObj, Intermedia } from '../../static/interface'; import { TooltipForIntermediate, TableObj, Intermedia, EventMap } from '../../static/interface';
import ReactEcharts from 'echarts-for-react'; import ReactEcharts from 'echarts-for-react';
require('echarts/lib/component/tooltip'); require('echarts/lib/component/tooltip');
require('echarts/lib/component/title'); require('echarts/lib/component/title');
...@@ -14,6 +14,8 @@ interface IntermediateState { ...@@ -14,6 +14,8 @@ interface IntermediateState {
isFilter: boolean; isFilter: boolean;
length: number; length: number;
clickCounts: number; // user filter intermediate click confirm btn's counts clickCounts: number; // user filter intermediate click confirm btn's counts
startMediaY: number;
endMediaY: number;
} }
interface IntermediateProps { interface IntermediateProps {
...@@ -38,7 +40,9 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -38,7 +40,9 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
isLoadconfirmBtn: false, isLoadconfirmBtn: false,
isFilter: false, isFilter: false,
length: 100000, length: 100000,
clickCounts: 0 clickCounts: 0,
startMediaY: 0,
endMediaY: 100
}; };
} }
...@@ -48,6 +52,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -48,6 +52,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
length: source.length, length: source.length,
detailSource: source detailSource: source
}); });
const { startMediaY, endMediaY } = this.state;
const trialIntermediate: Array<Intermedia> = []; const trialIntermediate: Array<Intermedia> = [];
Object.keys(source).map(item => { Object.keys(source).map(item => {
const temp = source[item]; const temp = source[item];
...@@ -113,6 +118,16 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -113,6 +118,16 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
type: 'value', type: 'value',
name: 'Metric' name: 'Metric'
}, },
dataZoom: [
{
id: 'dataZoomY',
type: 'inside',
yAxisIndex: [0],
filterMode: 'empty',
start: startMediaY,
end: endMediaY
}
],
series: trialIntermediate series: trialIntermediate
}; };
this.setState({ this.setState({
...@@ -258,6 +273,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -258,6 +273,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
render() { render() {
const { interSource, isLoadconfirmBtn, isFilter } = this.state; const { interSource, isLoadconfirmBtn, isFilter } = this.state;
const IntermediateEvents = { 'dataZoom': this.intermediateDataZoom };
return ( return (
<div> <div>
{/* style in para.scss */} {/* style in para.scss */}
...@@ -265,7 +281,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -265,7 +281,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
{ {
isFilter isFilter
? ?
<span style={{marginRight: 15}}> <span style={{ marginRight: 15 }}>
<span className="filter-x"># Intermediate result</span> <span className="filter-x"># Intermediate result</span>
<input <input
// placeholder="point" // placeholder="point"
...@@ -306,12 +322,22 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState> ...@@ -306,12 +322,22 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
option={interSource} option={interSource}
style={{ width: '100%', height: 418, margin: '0 auto' }} style={{ width: '100%', height: 418, margin: '0 auto' }}
notMerge={true} // update now notMerge={true} // update now
onEvents={IntermediateEvents}
/> />
<div className="yAxis"># Intermediate result</div> <div className="yAxis"># Intermediate result</div>
</Row> </Row>
</div> </div>
); );
} }
private intermediateDataZoom = (e: EventMap) => {
if (e.batch !== undefined) {
this.setState(() => ({
startMediaY: (e.batch[0].start !== null ? e.batch[0].start : 0),
endMediaY: (e.batch[0].end !== null ? e.batch[0].end : 100)
}));
}
}
} }
export default Intermediate; export default Intermediate;
...@@ -275,6 +275,7 @@ class Para extends React.Component<ParaProps, ParaState> { ...@@ -275,6 +275,7 @@ class Para extends React.Component<ParaProps, ParaState> {
parallelAxis.push({ parallelAxis.push({
dim: i, dim: i,
name: 'default metric', name: 'default metric',
scale: true,
nameTextStyle: { nameTextStyle: {
fontWeight: 700 fontWeight: 700
} }
......
...@@ -81,6 +81,7 @@ interface Dimobj { ...@@ -81,6 +81,7 @@ interface Dimobj {
axisLabel?: object; axisLabel?: object;
axisLine?: object; axisLine?: object;
nameTextStyle?: object; nameTextStyle?: object;
scale?: boolean;
} }
interface ParaObj { interface ParaObj {
...@@ -179,9 +180,13 @@ interface NNIManagerStatus { ...@@ -179,9 +180,13 @@ interface NNIManagerStatus {
errors: string[]; errors: string[];
} }
interface EventMap {
[key: string]: () => void;
}
export { export {
TableObj, TableRecord, Parameters, ExperimentProfile, AccurPoint, TableObj, TableRecord, Parameters, ExperimentProfile, AccurPoint,
DetailAccurPoint, TooltipForAccuracy, ParaObj, Dimobj, FinalType, DetailAccurPoint, TooltipForAccuracy, ParaObj, Dimobj, FinalType,
TooltipForIntermediate, SearchSpace, Intermedia, MetricDataRecord, TrialJobInfo, TooltipForIntermediate, SearchSpace, Intermedia, MetricDataRecord, TrialJobInfo,
NNIManagerStatus, NNIManagerStatus, EventMap
}; };
This source diff could not be displayed because it is too large. You can view the blob instead.
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