Skip to content
This repository has been archived by the owner on Sep 18, 2024. It is now read-only.

[webui] Support dict intermediate metrics(only for number type) #3895

Merged
merged 6 commits into from
Jul 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 54 additions & 5 deletions ts/webui/src/components/modals/Compare.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import * as React from 'react';
import { renderToString } from 'react-dom/server';
import { Stack, Modal, IconButton, IDragOptions, ContextualMenu } from '@fluentui/react';
import { Stack, Modal, IconButton, IDragOptions, ContextualMenu, Dropdown, IDropdownOption } from '@fluentui/react';
import ReactEcharts from 'echarts-for-react';
import { TooltipForIntermediate, TableObj, SingleAxis } from '../../static/interface';
import { contentStyles, iconButtonStyles } from '../buttons/ModalTheme';
import { convertDuration, parseMetrics } from '../../static/function';
import { EXPERIMENT, TRIALS } from '../../static/datamodel';
import '../../static/style/compare.scss';

/***
* Compare file is design for [each trial intermediate result and trials compare function]
* if trial has dict intermediate result, graph support shows all keys that type is number
*/

function _getWebUIWidth(): number {
return window.innerWidth;
}
Expand All @@ -20,7 +25,7 @@ const dragOptions: IDragOptions = {

// TODO: this should be refactored to the common modules
// copied from trial.ts
function _parseIntermediates(trial: TableObj): number[] {
function _parseIntermediates(trial: TableObj, key: string): number[] {
const intermediates: number[] = [];
for (const metric of trial.intermediates) {
if (metric === undefined) {
Expand All @@ -29,7 +34,7 @@ function _parseIntermediates(trial: TableObj): number[] {
const parsedMetric = parseMetrics(metric.data);
if (typeof parsedMetric === 'object') {
// TODO: should handle more types of metric keys
intermediates.push(parsedMetric.default);
intermediates.push(parsedMetric[key]);
} else {
intermediates.push(parsedMetric);
}
Expand All @@ -54,9 +59,17 @@ interface CompareProps {
changeSelectTrialIds?: () => void;
}

class Compare extends React.Component<CompareProps, {}> {
interface CompareState {
intermediateKey: string; // default, dict other keys
}

class Compare extends React.Component<CompareProps, CompareState> {
constructor(props: CompareProps) {
super(props);

this.state = {
intermediateKey: 'default'
};
}

private _generateTooltipSummary = (row: Item, value: string): string =>
Expand Down Expand Up @@ -206,8 +219,17 @@ class Compare extends React.Component<CompareProps, {}> {
onHideDialog();
};

private selectOtherKeys = (_event: React.FormEvent<HTMLDivElement>, item?: IDropdownOption): void => {
if (item !== undefined) {
this.setState(() => ({ intermediateKey: item.text }));
}
};

render(): React.ReactNode {
const { trials, title, showDetails } = this.props;
const { intermediateKey } = this.state;
let intermediateAllKeysList: string[] = [];

const flatten = (m: Map<SingleAxis, any>): Map<string, any> => {
return new Map(Array.from(m).map(([key, value]) => [key.baseName, value]));
};
Expand All @@ -218,9 +240,23 @@ class Compare extends React.Component<CompareProps, {}> {
duration: convertDuration(trial.duration),
parameters: flatten(trial.parameters(inferredSearchSpace)),
metrics: flatten(trial.metrics(TRIALS.inferredMetricSpace())),
intermediates: _parseIntermediates(trial)
intermediates: _parseIntermediates(trial, intermediateKey)
}));

if (trials[0].intermediates !== undefined && trials[0].intermediates[0]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if trials[0] has empty intermediates?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think empty intermediates is same as x.intermediates is undefined...

const parsedMetric = parseMetrics(trials[0].intermediates[0].data);
if (parsedMetric !== undefined && typeof parsedMetric === 'object') {
const allIntermediateKeys: string[] = [];
// just add type=number keys
for (const key in parsedMetric) {
if (typeof parsedMetric[key] === 'number') {
allIntermediateKeys.push(key);
}
}
intermediateAllKeysList = allIntermediateKeys;
}
}

return (
<Modal
isOpen={true}
Expand All @@ -240,6 +276,19 @@ class Compare extends React.Component<CompareProps, {}> {
onClick={this.closeCompareModal}
/>
</div>
{intermediateAllKeysList.length > 1 ? (
<Stack horizontalAlign='end' className='selectKeys'>
<Dropdown
className='select'
selectedKey={intermediateKey}
options={intermediateAllKeysList.map((key, item) => ({
key: key,
text: intermediateAllKeysList[item]
}))}
onChange={this.selectOtherKeys}
/>
</Stack>
) : null}
<Stack className='compare-modal-intermediate'>
{this._intermediates(items)}
<Stack className='compare-yAxis'># Intermediate result</Stack>
Expand Down
3 changes: 2 additions & 1 deletion ts/webui/src/static/style/search.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
.selectKeys {
/* intermediate result is dict, select box for keys */
.select {
margin-right: 12%;
margin-right: 6%;
margin-bottom: 15px;
}

.ms-Dropdown {
Expand Down