"tests/models/musicgen_melody/__init__.py" did not exist on "067395d5c56ef9026c442e691b6458ac196e3cf9"
DefaultMetricPoint.tsx 7.53 KB
Newer Older
1
import * as React from 'react';
2
import { Stack, Dropdown, Toggle, IDropdownOption } from '@fluentui/react';
3
import ReactEcharts from 'echarts-for-react';
Lijiaoa's avatar
Lijiaoa committed
4
5
6
7
import { Trial } from '@model/trial';
import { EXPERIMENT, TRIALS } from '@static/datamodel';
import { TooltipForAccuracy, EventMap } from '@static/interface';
import { reformatRetiariiParameter } from '@static/function';
8
import { gap15 } from '@components/fluent/ChildrenGap';
9
10
11
12
import 'echarts/lib/chart/scatter';
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';

Lijiao's avatar
Lijiao committed
13
14
15
16
17
18
const EmptyGraph = {
    grid: {
        left: '8%'
    },
    xAxis: {
        name: 'Trial',
19
        type: 'category'
Lijiao's avatar
Lijiao committed
20
21
22
    },
    yAxis: {
        name: 'Default metric',
23
        type: 'value'
Lijiao's avatar
Lijiao committed
24
25
    }
};
26

27
interface DefaultPointProps {
28
    trialIds: string[];
29
30
    chartHeight: number;
    hasBestCurve: boolean;
31
    changeExpandRowIDs: Function;
32
33
34
}

interface DefaultPointState {
35
    bestCurveEnabled?: boolean | undefined;
36
    startY: number; // dataZoomY
Lijiao's avatar
Lijiao committed
37
    endY: number;
38
    userSelectOptimizeMode: string;
39
40
41
42
43
}

class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState> {
    constructor(props: DefaultPointProps) {
        super(props);
Lijiao's avatar
Lijiao committed
44
45
46
        this.state = {
            bestCurveEnabled: false,
            startY: 0, // dataZoomY
47
48
            endY: 100,
            userSelectOptimizeMode: EXPERIMENT.optimizeMode || 'maximize'
Lijiao's avatar
Lijiao committed
49
        };
50
51
    }

52
    loadDefault = (ev: React.MouseEvent<HTMLElement>, checked?: boolean): void => {
53
        this.setState({ bestCurveEnabled: checked });
54
    };
55

56
57
58
    metricDataZoom = (e: EventMap): void => {
        if (e.batch !== undefined) {
            this.setState(() => ({
59
60
                startY: e.batch[0].start !== null ? e.batch[0].start : 0,
                endY: e.batch[0].end !== null ? e.batch[0].end : 100
61
62
            }));
        }
63
    };
64

65
    pointClick = (params: any): void => {
66
67
68
        // [hasBestCurve: true]: is detail page, otherwise, is overview page
        const { hasBestCurve } = this.props;
        if (!hasBestCurve) {
69
70
71
72
73
            this.props.changeExpandRowIDs(params.data[2], 'chart');
        }
    };

    generateGraphConfig(_maxSequenceId: number): any {
74
        const { startY, endY } = this.state;
75
        const { hasBestCurve } = this.props;
76
77
        return {
            grid: {
78
                left: '8%'
79
80
81
            },
            tooltip: {
                trigger: 'item',
82
                enterable: hasBestCurve,
83
                confine: true, // confirm always show tooltip box rather than hidden by background
84
85
86
87
88
                formatter: (data: TooltipForAccuracy): React.ReactNode => `
                    <div class="tooldetailAccuracy">
                        <div>Trial No.: ${data.data[0]}</div>
                        <div>Trial ID: ${data.data[2]}</div>
                        <div>Default metric: ${data.data[1]}</div>
89
90
91
92
93
                        <div>Parameters: <pre>${JSON.stringify(
                            reformatRetiariiParameter(data.data[3]),
                            null,
                            4
                        )}</pre></div>
94
95
                    </div>
                `
96
97
98
99
100
101
102
103
104
105
106
107
108
            },
            dataZoom: [
                {
                    id: 'dataZoomY',
                    type: 'inside',
                    yAxisIndex: [0],
                    filterMode: 'empty',
                    start: startY,
                    end: endY
                }
            ],
            xAxis: {
                name: 'Trial',
109
                type: 'category'
110
111
112
113
            },
            yAxis: {
                name: 'Default metric',
                type: 'value',
114
                scale: true
115
            },
116
            series: undefined
117
118
119
120
        };
    }

    generateScatterSeries(trials: Trial[]): any {
121
        const data = trials.map(trial => [trial.sequenceId, trial.accuracy, trial.id, trial.description.parameters]);
Lijiao's avatar
Lijiao committed
122
123
124
        return {
            symbolSize: 6,
            type: 'scatter',
125
            data
Lijiao's avatar
Lijiao committed
126
127
        };
    }
128
129

    generateBestCurveSeries(trials: Trial[]): any {
130
        const { userSelectOptimizeMode } = this.state;
Lijiao's avatar
Lijiao committed
131
        let best = trials[0];
132
        const data = [[best.sequenceId, best.accuracy, best.id, best.description.parameters]];
133

Lijiao's avatar
Lijiao committed
134
135
        for (let i = 1; i < trials.length; i++) {
            const trial = trials[i];
136
137
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            const delta = trial.accuracy! - best.accuracy!;
138
            const better = userSelectOptimizeMode === 'minimize' ? delta < 0 : delta > 0;
139
            if (better) {
140
                data.push([trial.sequenceId, trial.accuracy, best.id, trial.description.parameters]);
141
142
                best = trial;
            } else {
143
                data.push([trial.sequenceId, best.accuracy, best.id, trial.description.parameters]);
Lijiao's avatar
Lijiao committed
144
145
            }
        }
146

Lijiao's avatar
Lijiao committed
147
148
149
        return {
            type: 'line',
            lineStyle: { color: '#FF6600' },
150
            data
Lijiao's avatar
Lijiao committed
151
152
153
        };
    }

154
155
156
157
158
159
160
    // get user mode number 'max' or 'min'
    updateUserOptimizeMode = (event: React.FormEvent<HTMLDivElement>, item?: IDropdownOption): void => {
        if (item !== undefined) {
            this.setState({ userSelectOptimizeMode: item.key.toString() });
        }
    };

Lijiao's avatar
Lijiao committed
161
    render(): React.ReactNode {
162
        const { hasBestCurve, chartHeight } = this.props;
163
        const { userSelectOptimizeMode } = this.state;
164
        const graph = this.generateGraph();
165
        const accNodata = graph === EmptyGraph ? 'No data' : '';
166
        const onEvents = { dataZoom: this.metricDataZoom, click: this.pointClick };
167

168
169
        return (
            <div>
170
                {hasBestCurve && (
171
                    <Stack horizontal reversed tokens={gap15} className='default-metric'>
172
                        <Toggle label='Optimization curve' inlineLabel onChange={this.loadDefault} />
173
174
175
176
177
178
179
180
181
182
                        <Dropdown
                            selectedKey={userSelectOptimizeMode}
                            onChange={this.updateUserOptimizeMode}
                            options={[
                                { key: 'maximize', text: 'Maximize' },
                                { key: 'minimize', text: 'Minimize' }
                            ]}
                            styles={{ dropdown: { width: 100 } }}
                            className='para-filter-percent'
                        />
183
184
                    </Stack>
                )}
185
                <div className='default-metric-graph graph'>
186
187
188
189
                    <ReactEcharts
                        option={graph}
                        style={{
                            width: '100%',
190
                            height: chartHeight,
191
                            margin: '0 auto'
192
                        }}
193
                        theme='nni_theme'
194
195
196
                        notMerge={true} // update now
                        onEvents={onEvents}
                    />
Lijiaoa's avatar
Lijiaoa committed
197
                    <div className='default-metric-noData fontColor333'>{accNodata}</div>
198
                </div>
199
200
201
            </div>
        );
    }
202

Lijiao's avatar
Lijiao committed
203
    private generateGraph(): any {
204
205
206
207
        const trials = TRIALS.getTrials(this.props.trialIds).filter(trial => trial.sortable);
        if (trials.length === 0) {
            return EmptyGraph;
        }
Lijiao's avatar
Lijiao committed
208
        const graph = this.generateGraphConfig(trials[trials.length - 1].sequenceId);
209
        if (this.state.bestCurveEnabled) {
Lijiao's avatar
Lijiao committed
210
            (graph as any).series = [this.generateBestCurveSeries(trials), this.generateScatterSeries(trials)];
211
        } else {
Lijiao's avatar
Lijiao committed
212
            (graph as any).series = [this.generateScatterSeries(trials)];
213
214
215
216
217
218
        }
        return graph;
    }
}

export default DefaultPoint;