diff --git a/optuna_dashboard/static/components/GraphSlice.tsx b/optuna_dashboard/static/components/GraphSlice.tsx index 534a95aa..567ed437 100644 --- a/optuna_dashboard/static/components/GraphSlice.tsx +++ b/optuna_dashboard/static/components/GraphSlice.tsx @@ -1,246 +1,242 @@ import * as plotly from "plotly.js-basic-dist" import React, { ChangeEvent, FC, useEffect, useState } from "react" import { - Grid, + Grid, FormControl, InputLabel, MenuItem, - Select + Select, } from "@material-ui/core" -import { createStyles, makeStyles, Theme} from "@material-ui/core/styles" +import { createStyles, makeStyles, Theme } from "@material-ui/core/styles" const plotDomId = "graph-slice" const useStyles = makeStyles((theme: Theme) => -createStyles({ - formControl: { - marginBottom: theme.spacing(2), - marginRight: theme.spacing(5), - marginTop: theme.spacing(10) - }, -}) + createStyles({ + formControl: { + marginBottom: theme.spacing(2), + marginRight: theme.spacing(5), + marginTop: theme.spacing(10), + }, + }) ) export const GraphSlice: FC<{ - trials: Trial[] + trials: Trial[] }> = ({ trials = [] }) => { - const filteredTrials = trials.filter( - (t) => t.state === "Complete" || t.state === "Pruned" - ) - - let paramNames = new Set(trials[0].params.map((p) => p.name)) - filteredTrials.forEach((t) => { - paramNames = new Set( - t.params.filter((p) => paramNames.has(p.name)).map((p) => p.name) - ) - }) - const paramnames = Array.from(paramNames) + const filteredTrials = trials.filter( + (t) => t.state === "Complete" || t.state === "Pruned" + ) - const classes = useStyles() - const [xAxis, setXAxis] = useState(paramnames[0]) - - const handleXAxisChange = ( - e: ChangeEvent<{value: unknown}>) => { - setXAxis(e.target.value as string) + let paramNames = new Set(trials[0].params.map((p) => p.name)) + filteredTrials.forEach((t) => { + paramNames = new Set( + t.params.filter((p) => paramNames.has(p.name)).map((p) => p.name) + ) + }) + const paramnames = Array.from(paramNames) + + const classes = useStyles() + const [xAxis, setXAxis] = useState(paramnames[0]) + + const handleXAxisChange = (e: ChangeEvent<{ value: unknown }>) => { + setXAxis(e.target.value as string) + } + + useEffect(() => { + if (trials != null) { + plotSlice(trials, 0, xAxis) } - - useEffect(() => { - if(trials!=null){ - plotSlice( - trials, - 0, - xAxis - ) - } - }, - [trials, - xAxis - ]) + }, [trials, xAxis]) - return ( - - - - - Parameter - - - + return ( + + + + + Parameter + + - -
- - - ) + + +
+ + + ) } const plotSlice = (trials: Trial[], objectiveId: number, xAxis: string) => { - if(document.getElementById(plotDomId) === null){ - return - } - - const layout: Partial = { - title: "Slice", - margin: { - l: 50, - r: 50, - b: 0, - }, - } + if (document.getElementById(plotDomId) === null) { + return + } - if (trials.length === 0) { - plotly.react(plotDomId, [], layout) - return - } + const layout: Partial = { + title: "Slice", + margin: { + l: 50, + r: 50, + b: 0, + }, + } - const filteredTrials = trials.filter( - (t) => t.state === "Complete" || t.state === "Pruned" - ) - - let paramNames = new Set(trials[0].params.map((p) => p.name)) - filteredTrials.forEach((t) => { - paramNames = new Set( - t.params.filter((p) => paramNames.has(p.name)).map((p) => p.name) - ) - }) + if (trials.length === 0) { + plotly.react(plotDomId, [], layout) + return + } - const objectiveValues: number[] = filteredTrials.map( - (t) => t.values![objectiveId] + const filteredTrials = trials.filter( + (t) => t.state === "Complete" || t.state === "Pruned" + ) + + let paramNames = new Set(trials[0].params.map((p) => p.name)) + filteredTrials.forEach((t) => { + paramNames = new Set( + t.params.filter((p) => paramNames.has(p.name)).map((p) => p.name) ) + }) - if (paramNames.size === 0) { - plotly.react(plotDomId, []) - return + const objectiveValues: number[] = filteredTrials.map( + (t) => t.values![objectiveId] + ) + + if (paramNames.size === 0) { + plotly.react(plotDomId, []) + return + } else { + let trace: Partial[] = [ + { + type: "scatter", + x: [], + y: [], + mode: "markers", + xaxis: "x", + marker: { + color: "#185799", + }, + }, + ] + let updateLayout: Partial = { + title: "Slice", + margin: { + l: 50, + r: 50, + }, + xaxis: { + title: "x", + zerolinecolor: "#f2f5fa", + zerolinewidth: 1.5, + linecolor: "#f2f5fa", + linewidth: 5, + gridcolor: "#f2f5fa", + gridwidth: 1, + }, + yaxis: { + title: "Objective Values", + zerolinecolor: "#f2f5fa", + zerolinewidth: 2, + linecolor: "#f2f5fa", + linewidth: 5, + gridcolor: "#f2f5fa", + gridwidth: 1, + }, + plot_bgcolor: "#E5ecf6", + showlegend: false, } - else{ - let trace: Partial[] = [{ + paramNames.forEach((paramName) => { + const valueStrings = filteredTrials.map((t) => { + const param = t.params.find((p) => p.name == paramName) + return param!.value + }) + const isnum = valueStrings.every((v) => { + return !isNaN(parseFloat(v)) + }) + let values: number[] = [] + if (isnum) { + values = valueStrings.map((v) => parseFloat(v)) + if (paramName === xAxis) { + trace = [ + { + type: "scatter", + x: values, + y: objectiveValues, + mode: "markers", + xaxis: paramName, + marker: { + color: "#185799", + }, + }, + ] + updateLayout["xaxis"] = { + title: paramName, + zerolinecolor: "#f2f5fa", + zerolinewidth: 1.5, + linecolor: "#f2f5fa", + linewidth: 5, + gridcolor: "#f2f5fa", + gridwidth: 1, + } + plotly.react(plotDomId, trace, updateLayout) + } + } else { + const vocabSet = new Set(valueStrings) + const vocabArr = Array.from(vocabSet) + const values: number[] = valueStrings.map((v) => + vocabArr.findIndex((vocab) => v === vocab) + ) + const tickvals: number[] = vocabArr.map((v, i) => i) + trace = [ + { type: "scatter", - x: [], - y: [], + x: values, + y: objectiveValues, mode: "markers", - xaxis: "x", + // xaxis: paramName, marker: { - color: "#185799" - } - }] - let updateLayout: Partial = { - title: "Slice", - margin: { - l: 50, - r: 50, + color: "#185799", }, - xaxis: { - title: "x", - zerolinecolor: "#f2f5fa", - zerolinewidth: 1.5, - linecolor: "#f2f5fa", - linewidth: 5, - gridcolor: "#f2f5fa", - gridwidth: 1, + }, + ] + updateLayout = { + title: "Slice", + margin: { + l: 50, + r: 50, + }, + xaxis: { + title: paramName, + zerolinecolor: "#f2f5fa", + zerolinewidth: 1.5, + linecolor: "#f2f5fa", + linewidth: 5, + gridcolor: "#f2f5fa", + gridwidth: 1, + tickfont: { + color: "#000000", }, - yaxis: { - title: "Objective Values", - zerolinecolor: "#f2f5fa", - zerolinewidth: 2, - linecolor: "#f2f5fa", - linewidth: 5, - gridcolor: "#f2f5fa", - gridwidth: 1 - }, - plot_bgcolor: "#E5ecf6", - showlegend: false - } - paramNames.forEach((paramName) => { - const valueStrings = filteredTrials.map((t) => { - const param = t.params.find((p) => p.name == paramName) - return param!.value - }) - const isnum = valueStrings.every((v) => { - return !isNaN(parseFloat(v)) - }) - let values: number[] = [] - if(isnum){ - values = valueStrings.map((v) => parseFloat(v)) - if(paramName === xAxis){ - trace = [{ - type: "scatter", - x: values, - y: objectiveValues, - mode: "markers", - xaxis: paramName, - marker: { - color: "#185799" - } - }] - updateLayout["xaxis"]= { - title: paramName, - zerolinecolor: "#f2f5fa", - zerolinewidth: 1.5, - linecolor: "#f2f5fa", - linewidth: 5, - gridcolor: "#f2f5fa", - gridwidth: 1, - } - plotly.react(plotDomId, trace, updateLayout) - } - } - else{ - const vocabSet = new Set(valueStrings) - const vocabArr = Array.from(vocabSet) - const values: number[] = valueStrings.map((v) => - vocabArr.findIndex((vocab) => v === vocab) - ) - const tickvals: number[] = vocabArr.map((v, i) => i) - trace = [{ - type: "scatter", - x: values, - y: objectiveValues, - mode: "markers", - // xaxis: paramName, - marker: { - color: "#185799" - } - }] - updateLayout = { - title: "Slice", - margin: { - l: 50, - r: 50, - }, - xaxis: { - title: paramName, - zerolinecolor: "#f2f5fa", - zerolinewidth: 1.5, - linecolor: "#f2f5fa", - linewidth: 5, - gridcolor: "#f2f5fa", - gridwidth: 1, - tickfont: { - color: "#000000" - }, - tickvals: tickvals, - ticktext: vocabArr, - }, - yaxis: { - title: "Objective Values", - zerolinecolor: "#f2f5fa", - zerolinewidth: 2, - linecolor: "#f2f5fa", - linewidth: 5, - gridcolor: "#f2f5fa", - gridwidth: 1 - }, - plot_bgcolor: "#E5ecf6", - showlegend: false - } - plotly.react(plotDomId, trace, updateLayout) - } - }) - } + tickvals: tickvals, + ticktext: vocabArr, + }, + yaxis: { + title: "Objective Values", + zerolinecolor: "#f2f5fa", + zerolinewidth: 2, + linecolor: "#f2f5fa", + linewidth: 5, + gridcolor: "#f2f5fa", + gridwidth: 1, + }, + plot_bgcolor: "#E5ecf6", + showlegend: false, + } + plotly.react(plotDomId, trace, updateLayout) + } + }) + } } diff --git a/optuna_dashboard/static/components/StudyDetail.tsx b/optuna_dashboard/static/components/StudyDetail.tsx index dd283d85..55a2a61f 100644 --- a/optuna_dashboard/static/components/StudyDetail.tsx +++ b/optuna_dashboard/static/components/StudyDetail.tsx @@ -198,11 +198,11 @@ export const StudyDetail: FC = () => { ) : null} {studyDetail !== null && isSingleObjectiveStudy(studyDetail) ? ( - - - - - ) : null} + + + + + ) : null}