"vscode:/vscode.git/clone" did not exist on "c3faf2d6e673650b275bbefad9070706efddf3d3"
TrialsDetail.tsx 15.5 KB
Newer Older
Lijiao's avatar
Lijiao committed
1
2
3
import * as React from 'react';
import axios from 'axios';
import { MANAGER_IP } from '../static/const';
4
import { Row, Col, Tabs, Input, Select, Button, Icon } from 'antd';
5
const Option = Select.Option;
6
7
8
import { TableObj, Parameters } from '../static/interface';
import { getFinal } from '../static/function';
import DefaultPoint from './trial-detail/DefaultMetricPoint';
Lijiao's avatar
Lijiao committed
9
10
11
import Duration from './trial-detail/Duration';
import Title1 from './overview/Title1';
import Para from './trial-detail/Para';
12
import Intermediate from './trial-detail/Intermeidate';
Lijiao's avatar
Lijiao committed
13
14
15
16
17
18
19
import TableList from './trial-detail/TableList';
const TabPane = Tabs.TabPane;
import '../static/style/trialsDetail.scss';

interface TrialDetailState {
    accSource: object;
    accNodata: string;
Lijiao's avatar
Lijiao committed
20
21
    tableListSource: Array<TableObj>;
    searchResultSource: Array<TableObj>;
22
    isHasSearch: boolean;
23
    experimentStatus: string;
24
    entriesTable: number;
25
    experimentPlatform: string;
26
27
    searchSpace: string;
    defaultMetric?: Array<number>;
Lijiao's avatar
Lijiao committed
28
29
30
31
32
33
34
}

class TrialsDetail extends React.Component<{}, TrialDetailState> {

    public _isMounted = false;
    public interAccuracy = 0;
    public interTableList = 1;
35
    public interAllTableList = 2;
36

37
38
    public tableList: TableList | null;

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    private titleOfacc = (
        <Title1 text="Default Metric" icon="3.png" />
    );

    private titleOfhyper = (
        <Title1 text="Hyper Parameter" icon="1.png" />
    );

    private titleOfDuration = (
        <Title1 text="Trial Duration" icon="2.png" />
    );

    private titleOfIntermediate = (
        // <Title1 text="Intermediate Result" icon="intermediate.png" />
        <div className="panelTitle">
            <Icon type="line-chart" />
            <span>Intermediate Result</span>
        </div>
    );

Lijiao's avatar
Lijiao committed
59
60
61
62
63
64
    constructor(props: {}) {
        super(props);

        this.state = {
            accSource: {},
            accNodata: '',
Lijiao's avatar
Lijiao committed
65
            tableListSource: [],
66
67
68
            searchResultSource: [],
            experimentStatus: '',
            entriesTable: 20,
69
            isHasSearch: false,
70
71
72
            experimentPlatform: '',
            searchSpace: '',
            defaultMetric: [0, 1]
Lijiao's avatar
Lijiao committed
73
74
75
        };
    }

76
    getDetailSource = () => {
77
        this.isOffIntervals();
78
79
80
81
82
83
        axios
            .all([
                axios.get(`${MANAGER_IP}/trial-jobs`),
                axios.get(`${MANAGER_IP}/metric-data`)
            ])
            .then(axios.spread((res, res1) => {
84
85
                if (res.status === 200) {
                    const trialJobs = res.data;
86
                    const metricSource = res1.data;
Lijiao's avatar
Lijiao committed
87
                    const trialTable: Array<TableObj> = [];
88
89
90
                    Object.keys(trialJobs).map(item => {
                        // only succeeded trials have finalMetricData
                        let desc: Parameters = {
91
92
                            parameters: {},
                            intermediate: []
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
                        };
                        let duration = 0;
                        const id = trialJobs[item].id !== undefined
                            ? trialJobs[item].id
                            : '';
                        const status = trialJobs[item].status !== undefined
                            ? trialJobs[item].status
                            : '';
                        const begin = trialJobs[item].startTime;
                        const end = trialJobs[item].endTime;
                        if (begin) {
                            if (end) {
                                duration = (end - begin) / 1000;
                            } else {
                                duration = (new Date().getTime() - begin) / 1000;
                            }
                        }
                        if (trialJobs[item].hyperParameters !== undefined) {
                            const getPara = JSON.parse(trialJobs[item].hyperParameters[0]).parameters;
                            if (typeof getPara === 'string') {
                                desc.parameters = JSON.parse(getPara);
                            } else {
                                desc.parameters = getPara;
                            }
                        } else {
                            desc.parameters = { error: 'This trial\'s parameters are not available.' };
                        }
                        if (trialJobs[item].logPath !== undefined) {
                            desc.logPath = trialJobs[item].logPath;
                        }
123

124
                        const acc = getFinal(trialJobs[item].finalMetricData);
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
                        // deal with intermediate result list
                        const mediate: Array<number> = [];
                        Object.keys(metricSource).map(key => {
                            const items = metricSource[key];
                            if (items.trialJobId === id) {
                                // succeed trial, last intermediate result is final result
                                // final result format may be object 
                                if (typeof JSON.parse(items.data) === 'object') {
                                    mediate.push(JSON.parse(items.data).default);
                                } else {
                                    mediate.push(JSON.parse(items.data));
                                }
                            }
                        });
                        desc.intermediate = mediate;
140
141
142
143
144
145
146
147
148
149
                        trialTable.push({
                            key: trialTable.length,
                            sequenceId: trialJobs[item].sequenceId,
                            id: id,
                            status: status,
                            duration: duration,
                            acc: acc,
                            description: desc
                        });
                    });
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
                    // get acc max and min for hyper-parameters graph color bar max and min
                    const sortSource = JSON.parse(JSON.stringify(trialTable));
                    sortSource.sort((a: TableObj, b: TableObj) => {
                        if (a.acc !== undefined && b.acc !== undefined) {
                            return JSON.parse(a.acc.default) - JSON.parse(b.acc.default);
                        } else {
                            return NaN;
                        }
                    });

                    if (this._isMounted && sortSource !== undefined) {

                        const hyperMin = sortSource[0].acc !== undefined
                            ?
                            sortSource[0].acc.default
                            :
                            '0';
                        const max = sortSource[sortSource.length - 1].acc;
                        let maxResult = '1';
                        if (max !== undefined) {
                            maxResult = max.default;
                        }
                        this.setState(() => ({
                            defaultMetric: [JSON.parse(hyperMin), JSON.parse(maxResult)]
                        }));
                    }
                    // update search data result
177
178
179
180
181
182
                    const { searchResultSource } = this.state;
                    if (searchResultSource.length !== 0) {
                        const temp: Array<number> = [];
                        Object.keys(searchResultSource).map(index => {
                            temp.push(searchResultSource[index].id);
                        });
Lijiao's avatar
Lijiao committed
183
                        const searchResultList: Array<TableObj> = [];
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
                        for (let i = 0; i < temp.length; i++) {
                            Object.keys(trialTable).map(key => {
                                const item = trialTable[key];
                                if (item.id === temp[i]) {
                                    searchResultList.push(item);
                                }
                            });
                        }

                        if (this._isMounted) {
                            this.setState(() => ({
                                searchResultSource: searchResultList
                            }));
                        }
                    }
                    if (this._isMounted) {
                        this.setState(() => ({
                            tableListSource: trialTable
                        }));
                    }
                }
205
            }));
Lijiao's avatar
Lijiao committed
206
207
    }

208
209
210
211
    // search a trial by trial No. & trial id
    searchTrial = (event: React.ChangeEvent<HTMLInputElement>) => {
        const targetValue = event.target.value;
        if (targetValue === '' || targetValue === ' ') {
212
213
214
215
216
217
218
            const { tableListSource } = this.state;
            if (this._isMounted) {
                this.setState(() => ({
                    isHasSearch: false,
                    tableListSource: tableListSource,
                }));
            }
219
220
        } else {
            const { tableListSource } = this.state;
Lijiao's avatar
Lijiao committed
221
            const searchResultList: Array<TableObj> = [];
222
223
            Object.keys(tableListSource).map(key => {
                const item = tableListSource[key];
224
225
226
227
                if (item.sequenceId.toString() === targetValue
                    || item.id.includes(targetValue)
                    || item.status.includes(targetValue)
                ) {
228
229
230
231
232
233
234
235
                    searchResultList.push(item);
                }
            });
            if (this._isMounted) {
                this.setState(() => ({
                    searchResultSource: searchResultList,
                    isHasSearch: true
                }));
236
237
238
            }
        }
    }
239

240
    // close timer
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
    isOffIntervals = () => {
        axios(`${MANAGER_IP}/check-status`, {
            method: 'GET'
        })
            .then(res => {
                if (res.status === 200 && this._isMounted) {
                    switch (res.data.status) {
                        case 'DONE':
                        case 'ERROR':
                        case 'STOPPED':
                            window.clearInterval(this.interTableList);
                            break;
                        default:
                    }
                }
            });
    }

259
260
261
262
263
264
265
266
267
268
269
270
    handleEntriesSelect = (value: string) => {
        switch (value) {
            case '20':
                this.setState(() => ({ entriesTable: 20 }));
                break;
            case '50':
                this.setState(() => ({ entriesTable: 50 }));
                break;
            case '100':
                this.setState(() => ({ entriesTable: 100 }));
                break;
            case 'all':
271
272
                const { tableListSource } = this.state;
                this.setState(() => ({ entriesTable: tableListSource.length }));
273
274
275
276
277
                break;
            default:
        }
    }

278
279
280
281
    test = () => {
        alert('TableList component was not properly initialized.');
    }

282
283
284
285
286
287
288
    checkExperimentPlatform = () => {
        axios(`${MANAGER_IP}/experiment`, {
            method: 'GET'
        })
            .then(res => {
                if (res.status === 200) {
                    const trainingPlatform = res.data.params.trainingServicePlatform !== undefined
289
290
291
292
                        ?
                        res.data.params.trainingServicePlatform
                        :
                        '';
293
294
                    if (this._isMounted) {
                        this.setState({
295
296
                            experimentPlatform: trainingPlatform,
                            searchSpace: res.data.params.searchSpace
297
298
299
300
301
302
                        });
                    }
                }
            });
    }

Lijiao's avatar
Lijiao committed
303
304
305
    componentDidMount() {

        this._isMounted = true;
306
307
        this.getDetailSource();
        this.interTableList = window.setInterval(this.getDetailSource, 10000);
308
        this.checkExperimentPlatform();
Lijiao's avatar
Lijiao committed
309
310
311
312
313
314
315
316
    }

    componentWillUnmount() {
        this._isMounted = false;
        window.clearInterval(this.interTableList);
    }

    render() {
317
318
319
320
321

        const {
            tableListSource, searchResultSource, isHasSearch,
            entriesTable, experimentPlatform, searchSpace,
            defaultMetric
322
        } = this.state;
323
        const source = isHasSearch ? searchResultSource : tableListSource;
Lijiao's avatar
Lijiao committed
324
325
326
        return (
            <div>
                <div className="trial" id="tabsty">
327
328
                    <Tabs type="card">
                        <TabPane tab={this.titleOfacc} key="1">
Lijiao's avatar
Lijiao committed
329
                            <Row className="graph">
330
                                <DefaultPoint
Lijiao's avatar
Lijiao committed
331
                                    height={432}
332
333
334
335
336
337
338
339
340
341
                                    showSource={source}
                                />
                            </Row>
                        </TabPane>
                        <TabPane tab={this.titleOfhyper} key="2">
                            <Row className="graph">
                                <Para
                                    dataSource={source}
                                    expSearchSpace={searchSpace}
                                    defaultMetric={defaultMetric}
Lijiao's avatar
Lijiao committed
342
343
344
                                />
                            </Row>
                        </TabPane>
345
346
                        <TabPane tab={this.titleOfDuration} key="3">
                            <Duration source={source} />
Lijiao's avatar
Lijiao committed
347
                        </TabPane>
348
349
                        <TabPane tab={this.titleOfIntermediate} key="4">
                            <Intermediate source={source} />
Lijiao's avatar
Lijiao committed
350
351
352
353
                        </TabPane>
                    </Tabs>
                </div>
                {/* trial table list */}
354
                <Title1 text="Trial Jobs" icon="6.png" />
355
356
                <Row className="allList">
                    <Col span={12}>
357
358
359
360
361
362
363
364
365
366
367
368
                        <span>show</span>
                        <Select
                            className="entry"
                            onSelect={this.handleEntriesSelect}
                            defaultValue="20"
                        >
                            <Option value="20">20</Option>
                            <Option value="50">50</Option>
                            <Option value="100">100</Option>
                            <Option value="all">All</Option>
                        </Select>
                        <span>entries</span>
369
                    </Col>
370
                    <Col span={12} className="right">
371
372
373
374
375
376
377
378
379
380
381
382
383
                        <Row>
                            <Col span={12}>
                                <Button
                                    type="primary"
                                    className="tableButton editStyle"
                                    onClick={this.tableList ? this.tableList.addColumn : this.test}
                                >
                                    AddColumn
                                </Button>
                            </Col>
                            <Col span={12}>
                                <Input
                                    type="text"
384
                                    placeholder="search by Id, Trial No. or Status"
385
                                    onChange={this.searchTrial}
386
                                    style={{ width: 230, marginLeft: 6 }}
387
388
389
                                />
                            </Col>
                        </Row>
390
391
                    </Col>
                </Row>
Lijiao's avatar
Lijiao committed
392
                <TableList
393
                    entries={entriesTable}
394
395
                    tableSource={source}
                    updateList={this.getDetailSource}
396
                    platform={experimentPlatform}
397
                    ref={(tabList) => this.tableList = tabList}
Lijiao's avatar
Lijiao committed
398
399
400
401
402
403
404
                />
            </div>
        );
    }
}

export default TrialsDetail;