mirror of
https://github.com/wassname/optuna-dashboard.git
synced 2026-09-11 12:30:25 +08:00
Merge pull request #865 from porink0424/feat/lazy-loading-graphs
Impl lazy loading for graph components
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { Box, Typography, useTheme } from "@mui/material"
|
||||
import React from "react"
|
||||
import { GraphComponentState } from "ts/types/optuna"
|
||||
|
||||
function GraphContainer({
|
||||
plotDomId,
|
||||
graphComponentState,
|
||||
}: {
|
||||
plotDomId: string
|
||||
graphComponentState: GraphComponentState
|
||||
}) {
|
||||
const theme = useTheme()
|
||||
return (
|
||||
<Box component="div" id={plotDomId} sx={{ height: "450px" }}>
|
||||
{graphComponentState !== "graphDidRender" && (
|
||||
<Box
|
||||
component="div"
|
||||
sx={{
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<Typography color={theme.palette.grey[700]}>Loading...</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default GraphContainer
|
||||
@@ -17,10 +17,12 @@ import React, { FC, useEffect, useMemo, useState } from "react"
|
||||
import { SearchSpaceItem, StudyDetail, Trial } from "ts/types/optuna"
|
||||
import { PlotType } from "../apiClient"
|
||||
import { getAxisInfo } from "../graphUtil"
|
||||
import { useGraphComponentState } from "../hooks/useGraphComponentState"
|
||||
import { usePlot } from "../hooks/usePlot"
|
||||
import { useMergedUnionSearchSpace } from "../searchSpace"
|
||||
import { usePlotlyColorTheme } from "../state"
|
||||
import { useBackendRender } from "../state"
|
||||
import GraphContainer from "./GraphContainer"
|
||||
|
||||
const plotDomId = "graph-contour"
|
||||
const CONTOUR_DISABLED_THRESHOLD = 100
|
||||
@@ -84,6 +86,8 @@ const DisabledContour: FC<{
|
||||
const ContourBackend: FC<{
|
||||
study: StudyDetail | null
|
||||
}> = ({ study = null }) => {
|
||||
const { graphComponentState, notifyGraphDidRender } = useGraphComponentState()
|
||||
|
||||
const studyId = study?.id
|
||||
const numCompletedTrials =
|
||||
study?.trials.filter((t) => t.state === "Complete").length || 0
|
||||
@@ -94,22 +98,29 @@ const ContourBackend: FC<{
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (data && layout) {
|
||||
plotly.react(plotDomId, data, layout)
|
||||
if (data && layout && graphComponentState !== "componentWillMount") {
|
||||
plotly.react(plotDomId, data, layout).then(notifyGraphDidRender)
|
||||
}
|
||||
}, [data, layout])
|
||||
}, [data, layout, graphComponentState])
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}, [error])
|
||||
|
||||
return <Box component="div" id={plotDomId} sx={{ height: "450px" }} />
|
||||
return (
|
||||
<GraphContainer
|
||||
plotDomId={plotDomId}
|
||||
graphComponentState={graphComponentState}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const ContourFrontend: FC<{
|
||||
study: StudyDetail | null
|
||||
}> = ({ study = null }) => {
|
||||
const { graphComponentState, notifyGraphDidRender } = useGraphComponentState()
|
||||
|
||||
const theme = useTheme()
|
||||
const colorTheme = usePlotlyColorTheme(theme.palette.mode)
|
||||
|
||||
@@ -139,10 +150,12 @@ const ContourFrontend: FC<{
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (study != null) {
|
||||
plotContour(study, objectiveId, xParam, yParam, colorTheme)
|
||||
if (study != null && graphComponentState !== "componentWillMount") {
|
||||
plotContour(study, objectiveId, xParam, yParam, colorTheme)?.then(
|
||||
notifyGraphDidRender
|
||||
)
|
||||
}
|
||||
}, [study, objectiveId, xParam, yParam, colorTheme])
|
||||
}, [study, objectiveId, xParam, yParam, colorTheme, graphComponentState])
|
||||
|
||||
const space: SearchSpaceItem[] = study ? study.union_search_space : []
|
||||
|
||||
@@ -201,7 +214,10 @@ const ContourFrontend: FC<{
|
||||
) : null}
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<Box component="div" id={plotDomId} sx={{ height: "450px" }} />
|
||||
<GraphContainer
|
||||
plotDomId={plotDomId}
|
||||
graphComponentState={graphComponentState}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
@@ -225,10 +241,9 @@ const plotContour = (
|
||||
const trials: Trial[] = study ? study.trials : []
|
||||
const filteredTrials = trials.filter((t) => filterFunc(t))
|
||||
if (filteredTrials.length < 2 || xParam === null || yParam === null) {
|
||||
plotly.react(plotDomId, [], {
|
||||
return plotly.react(plotDomId, [], {
|
||||
template: colorTheme,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const xAxis = getAxisInfo(trials, xParam)
|
||||
@@ -257,8 +272,7 @@ const plotContour = (
|
||||
|
||||
// TODO(c-bata): Support parameters that only have the single value
|
||||
if (xIndices.length <= 1 || yIndices.length <= 1) {
|
||||
plotly.react(plotDomId, [], layout)
|
||||
return
|
||||
return plotly.react(plotDomId, [], layout)
|
||||
}
|
||||
|
||||
const xValues: plotly.Datum[] = []
|
||||
@@ -322,8 +336,7 @@ const plotContour = (
|
||||
showlegend: false,
|
||||
},
|
||||
]
|
||||
plotly.react(plotDomId, plotData, layout)
|
||||
return
|
||||
return plotly.react(plotDomId, plotData, layout)
|
||||
}
|
||||
|
||||
layout.legend = {
|
||||
@@ -351,5 +364,5 @@ const plotContour = (
|
||||
mode: "markers",
|
||||
},
|
||||
]
|
||||
plotly.react(plotDomId, plotData, layout)
|
||||
return plotly.react(plotDomId, plotData, layout)
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ import * as plotly from "plotly.js-dist-min"
|
||||
import React, { FC, useEffect, useMemo } from "react"
|
||||
import { StudyDetail, Trial } from "ts/types/optuna"
|
||||
import { CompareStudiesPlotType, getCompareStudiesPlotAPI } from "../apiClient"
|
||||
import { useGraphComponentState } from "../hooks/useGraphComponentState"
|
||||
import { useBackendRender, usePlotlyColorTheme } from "../state"
|
||||
import { Target, useFilteredTrialsFromStudies } from "../trialFilter"
|
||||
import GraphContainer from "./GraphContainer"
|
||||
|
||||
const getPlotDomId = (objectiveId: number) => `graph-edf-${objectiveId}`
|
||||
|
||||
@@ -27,6 +29,8 @@ export const GraphEdf: FC<{
|
||||
const GraphEdfBackend: FC<{
|
||||
studies: StudyDetail[]
|
||||
}> = ({ studies }) => {
|
||||
const { graphComponentState, notifyGraphDidRender } = useGraphComponentState()
|
||||
|
||||
const studyIds = studies.map((s) => s.id)
|
||||
const domId = getPlotDomId(-1)
|
||||
const numCompletedTrials = studies.reduce(
|
||||
@@ -38,21 +42,30 @@ const GraphEdfBackend: FC<{
|
||||
if (studyIds.length === 0) {
|
||||
return
|
||||
}
|
||||
getCompareStudiesPlotAPI(studyIds, CompareStudiesPlotType.EDF)
|
||||
.then(({ data, layout }) => {
|
||||
plotly.react(domId, data, layout)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
})
|
||||
}, [studyIds, numCompletedTrials])
|
||||
return <Box component="div" id={domId} sx={{ height: "450px" }} />
|
||||
if (graphComponentState !== "componentWillMount") {
|
||||
getCompareStudiesPlotAPI(studyIds, CompareStudiesPlotType.EDF)
|
||||
.then(({ data, layout }) => {
|
||||
plotly.react(domId, data, layout).then(notifyGraphDidRender)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
}, [studyIds, numCompletedTrials, graphComponentState])
|
||||
return (
|
||||
<GraphContainer
|
||||
plotDomId={domId}
|
||||
graphComponentState={graphComponentState}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const GraphEdfFrontend: FC<{
|
||||
studies: StudyDetail[]
|
||||
objectiveId: number
|
||||
}> = ({ studies, objectiveId }) => {
|
||||
const { graphComponentState, notifyGraphDidRender } = useGraphComponentState()
|
||||
|
||||
const theme = useTheme()
|
||||
const colorTheme = usePlotlyColorTheme(theme.palette.mode)
|
||||
|
||||
@@ -71,8 +84,12 @@ const GraphEdfFrontend: FC<{
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
plotEdf(edfPlotInfos, target, domId, colorTheme)
|
||||
}, [studies, target, colorTheme])
|
||||
if (graphComponentState !== "componentWillMount") {
|
||||
plotEdf(edfPlotInfos, target, domId, colorTheme)?.then(
|
||||
notifyGraphDidRender
|
||||
)
|
||||
}
|
||||
}, [studies, target, colorTheme, graphComponentState])
|
||||
|
||||
return (
|
||||
<Box component="div">
|
||||
@@ -82,7 +99,10 @@ const GraphEdfFrontend: FC<{
|
||||
>
|
||||
{`EDF for ${target.toLabel(studies[0].objective_names)}`}
|
||||
</Typography>
|
||||
<Box component="div" id={domId} sx={{ height: "450px" }} />
|
||||
<GraphContainer
|
||||
plotDomId={domId}
|
||||
graphComponentState={graphComponentState}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -97,10 +117,9 @@ const plotEdf = (
|
||||
return
|
||||
}
|
||||
if (edfPlotInfos.length === 0) {
|
||||
plotly.react(domId, [], {
|
||||
return plotly.react(domId, [], {
|
||||
template: colorTheme,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const target_name = "Objective Value"
|
||||
@@ -147,5 +166,5 @@ const plotEdf = (
|
||||
y: yValues,
|
||||
}
|
||||
})
|
||||
plotly.react(domId, plotData, layout)
|
||||
return plotly.react(domId, plotData, layout)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
Box,
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
FormGroup,
|
||||
@@ -11,6 +10,7 @@ import * as plotly from "plotly.js-dist-min"
|
||||
import React, { FC, ReactNode, useEffect, useState } from "react"
|
||||
import { SearchSpaceItem, StudyDetail, Trial } from "ts/types/optuna"
|
||||
import { PlotType } from "../apiClient"
|
||||
import { useGraphComponentState } from "../hooks/useGraphComponentState"
|
||||
import { usePlot } from "../hooks/usePlot"
|
||||
import { useMergedUnionSearchSpace } from "../searchSpace"
|
||||
import { usePlotlyColorTheme } from "../state"
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
useObjectiveAndUserAttrTargets,
|
||||
useParamTargets,
|
||||
} from "../trialFilter"
|
||||
import GraphContainer from "./GraphContainer"
|
||||
|
||||
const plotDomId = "graph-parallel-coordinate"
|
||||
|
||||
@@ -101,6 +102,8 @@ export const GraphParallelCoordinate: FC<{
|
||||
const GraphParallelCoordinateBackend: FC<{
|
||||
study: StudyDetail | null
|
||||
}> = ({ study = null }) => {
|
||||
const { graphComponentState, notifyGraphDidRender } = useGraphComponentState()
|
||||
|
||||
const studyId = study?.id
|
||||
const numCompletedTrials =
|
||||
study?.trials.filter((t) => t.state === "Complete").length || 0
|
||||
@@ -112,22 +115,29 @@ const GraphParallelCoordinateBackend: FC<{
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (data && layout) {
|
||||
plotly.react(plotDomId, data, layout)
|
||||
if (data && layout && graphComponentState !== "componentWillMount") {
|
||||
plotly.react(plotDomId, data, layout).then(notifyGraphDidRender)
|
||||
}
|
||||
}, [data, layout])
|
||||
}, [data, layout, graphComponentState])
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}, [error])
|
||||
|
||||
return <Box component="div" id={plotDomId} sx={{ height: "450px" }} />
|
||||
return (
|
||||
<GraphContainer
|
||||
plotDomId={plotDomId}
|
||||
graphComponentState={graphComponentState}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const GraphParallelCoordinateFrontend: FC<{
|
||||
study: StudyDetail | null
|
||||
}> = ({ study = null }) => {
|
||||
const { graphComponentState, notifyGraphDidRender } = useGraphComponentState()
|
||||
|
||||
const theme = useTheme()
|
||||
const colorTheme = usePlotlyColorTheme(theme.palette.mode)
|
||||
|
||||
@@ -135,10 +145,12 @@ const GraphParallelCoordinateFrontend: FC<{
|
||||
|
||||
const trials = useFilteredTrials(study, targets, false)
|
||||
useEffect(() => {
|
||||
if (study !== null) {
|
||||
plotCoordinate(study, trials, targets, searchSpace, colorTheme)
|
||||
if (study !== null && graphComponentState !== "componentWillMount") {
|
||||
plotCoordinate(study, trials, targets, searchSpace, colorTheme)?.then(
|
||||
notifyGraphDidRender
|
||||
)
|
||||
}
|
||||
}, [study, trials, targets, searchSpace, colorTheme])
|
||||
}, [study, trials, targets, searchSpace, colorTheme, graphComponentState])
|
||||
|
||||
return (
|
||||
<Grid container direction="row">
|
||||
@@ -162,7 +174,10 @@ const GraphParallelCoordinateFrontend: FC<{
|
||||
{renderCheckBoxes()}
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<Box component="div" id={plotDomId} sx={{ height: "450px" }} />
|
||||
<GraphContainer
|
||||
plotDomId={plotDomId}
|
||||
graphComponentState={graphComponentState}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
@@ -190,8 +205,7 @@ const plotCoordinate = (
|
||||
uirevision: "true",
|
||||
}
|
||||
if (trials.length === 0 || targets.length === 0) {
|
||||
plotly.react(plotDomId, [], layout)
|
||||
return
|
||||
return plotly.react(plotDomId, [], layout)
|
||||
}
|
||||
|
||||
const maxLabelLength = 40
|
||||
@@ -282,8 +296,7 @@ const plotCoordinate = (
|
||||
})
|
||||
if (dimensions.length === 0) {
|
||||
console.log("Must not reach here.")
|
||||
plotly.react(plotDomId, [], layout)
|
||||
return
|
||||
return plotly.react(plotDomId, [], layout)
|
||||
}
|
||||
let reversescale = false
|
||||
if (
|
||||
@@ -312,5 +325,5 @@ const plotCoordinate = (
|
||||
},
|
||||
]
|
||||
|
||||
plotly.react(plotDomId, plotData, layout)
|
||||
return plotly.react(plotDomId, plotData, layout)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
Box,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Grid,
|
||||
@@ -14,9 +13,11 @@ import React, { FC, useEffect, useState } from "react"
|
||||
import { SearchSpaceItem, StudyDetail, Trial } from "ts/types/optuna"
|
||||
import { PlotType } from "../apiClient"
|
||||
import { getAxisInfo, makeHovertext } from "../graphUtil"
|
||||
import { useGraphComponentState } from "../hooks/useGraphComponentState"
|
||||
import { usePlot } from "../hooks/usePlot"
|
||||
import { useMergedUnionSearchSpace } from "../searchSpace"
|
||||
import { useBackendRender, usePlotlyColorTheme } from "../state"
|
||||
import GraphContainer from "./GraphContainer"
|
||||
|
||||
const plotDomId = "graph-rank"
|
||||
|
||||
@@ -45,6 +46,8 @@ export const GraphRank: FC<{
|
||||
const GraphRankBackend: FC<{
|
||||
study: StudyDetail | null
|
||||
}> = ({ study = null }) => {
|
||||
const { graphComponentState, notifyGraphDidRender } = useGraphComponentState()
|
||||
|
||||
const studyId = study?.id
|
||||
const numCompletedTrials =
|
||||
study?.trials.filter((t) => t.state === "Complete").length || 0
|
||||
@@ -56,22 +59,29 @@ const GraphRankBackend: FC<{
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (data && layout) {
|
||||
plotly.react(plotDomId, data, layout)
|
||||
if (data && layout && graphComponentState !== "componentWillMount") {
|
||||
plotly.react(plotDomId, data, layout).then(notifyGraphDidRender)
|
||||
}
|
||||
}, [data, layout])
|
||||
}, [data, layout, graphComponentState])
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}, [error])
|
||||
|
||||
return <Box component="div" id={plotDomId} sx={{ height: "450px" }} />
|
||||
return (
|
||||
<GraphContainer
|
||||
plotDomId={plotDomId}
|
||||
graphComponentState={graphComponentState}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const GraphRankFrontend: FC<{
|
||||
study: StudyDetail | null
|
||||
}> = ({ study = null }) => {
|
||||
const { graphComponentState, notifyGraphDidRender } = useGraphComponentState()
|
||||
|
||||
const theme = useTheme()
|
||||
const colorTheme = usePlotlyColorTheme(theme.palette.mode)
|
||||
|
||||
@@ -101,11 +111,19 @@ const GraphRankFrontend: FC<{
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (study != null) {
|
||||
if (study != null && graphComponentState !== "componentWillMount") {
|
||||
const rankPlotInfo = getRankPlotInfo(study, objectiveId, xParam, yParam)
|
||||
plotRank(rankPlotInfo, colorTheme)
|
||||
plotRank(rankPlotInfo, colorTheme)?.then(notifyGraphDidRender)
|
||||
}
|
||||
}, [study, objectiveId, xParam, yParam, theme.palette.mode, colorTheme])
|
||||
}, [
|
||||
study,
|
||||
objectiveId,
|
||||
xParam,
|
||||
yParam,
|
||||
theme.palette.mode,
|
||||
colorTheme,
|
||||
graphComponentState,
|
||||
])
|
||||
|
||||
const space: SearchSpaceItem[] = study ? study.union_search_space : []
|
||||
|
||||
@@ -164,7 +182,10 @@ const GraphRankFrontend: FC<{
|
||||
) : null}
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<Box component="div" id={plotDomId} sx={{ height: "450px" }} />
|
||||
<GraphContainer
|
||||
plotDomId={plotDomId}
|
||||
graphComponentState={graphComponentState}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
@@ -301,10 +322,9 @@ const plotRank = (
|
||||
}
|
||||
|
||||
if (rankPlotInfo === null) {
|
||||
plotly.react(plotDomId, [], {
|
||||
return plotly.react(plotDomId, [], {
|
||||
template: colorTheme,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const layout: Partial<plotly.Layout> = {
|
||||
@@ -375,5 +395,5 @@ const plotRank = (
|
||||
),
|
||||
},
|
||||
]
|
||||
plotly.react(plotDomId, plotData, layout)
|
||||
return plotly.react(plotDomId, plotData, layout)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
Box,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Grid,
|
||||
@@ -14,6 +13,7 @@ import * as plotly from "plotly.js-dist-min"
|
||||
import React, { FC, useEffect, useState } from "react"
|
||||
import { SearchSpaceItem, StudyDetail, Trial } from "ts/types/optuna"
|
||||
import { PlotType } from "../apiClient"
|
||||
import { useGraphComponentState } from "../hooks/useGraphComponentState"
|
||||
import { usePlot } from "../hooks/usePlot"
|
||||
import { useMergedUnionSearchSpace } from "../searchSpace"
|
||||
import { useBackendRender, usePlotlyColorTheme } from "../state"
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
useObjectiveAndUserAttrTargets,
|
||||
useParamTargets,
|
||||
} from "../trialFilter"
|
||||
import GraphContainer from "./GraphContainer"
|
||||
|
||||
const plotDomId = "graph-slice"
|
||||
|
||||
@@ -46,6 +47,8 @@ export const GraphSlice: FC<{
|
||||
const GraphSliceBackend: FC<{
|
||||
study: StudyDetail | null
|
||||
}> = ({ study = null }) => {
|
||||
const { graphComponentState, notifyGraphDidRender } = useGraphComponentState()
|
||||
|
||||
const studyId = study?.id
|
||||
const numCompletedTrials =
|
||||
study?.trials.filter((t) => t.state === "Complete").length || 0
|
||||
@@ -57,22 +60,29 @@ const GraphSliceBackend: FC<{
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (data && layout) {
|
||||
plotly.react(plotDomId, data, layout)
|
||||
if (data && layout && graphComponentState !== "componentWillMount") {
|
||||
plotly.react(plotDomId, data, layout).then(notifyGraphDidRender)
|
||||
}
|
||||
}, [data, layout])
|
||||
}, [data, layout, graphComponentState])
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}, [error])
|
||||
|
||||
return <Box component="div" id={plotDomId} sx={{ height: "450px" }} />
|
||||
return (
|
||||
<GraphContainer
|
||||
plotDomId={plotDomId}
|
||||
graphComponentState={graphComponentState}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const GraphSliceFrontend: FC<{
|
||||
study: StudyDetail | null
|
||||
}> = ({ study = null }) => {
|
||||
const { graphComponentState, notifyGraphDidRender } = useGraphComponentState()
|
||||
|
||||
const theme = useTheme()
|
||||
const colorTheme = usePlotlyColorTheme(theme.palette.mode)
|
||||
|
||||
@@ -92,14 +102,16 @@ const GraphSliceFrontend: FC<{
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
plotSlice(
|
||||
trials,
|
||||
selectedObjective,
|
||||
selectedParamTarget,
|
||||
searchSpace.find((s) => s.name === selectedParamTarget?.key) || null,
|
||||
logYScale,
|
||||
colorTheme
|
||||
)
|
||||
if (graphComponentState !== "componentWillMount") {
|
||||
plotSlice(
|
||||
trials,
|
||||
selectedObjective,
|
||||
selectedParamTarget,
|
||||
searchSpace.find((s) => s.name === selectedParamTarget?.key) || null,
|
||||
logYScale,
|
||||
colorTheme
|
||||
)?.then(notifyGraphDidRender)
|
||||
}
|
||||
}, [
|
||||
trials,
|
||||
selectedObjective,
|
||||
@@ -107,6 +119,7 @@ const GraphSliceFrontend: FC<{
|
||||
selectedParamTarget,
|
||||
logYScale,
|
||||
colorTheme,
|
||||
graphComponentState,
|
||||
])
|
||||
|
||||
const handleObjectiveChange = (event: SelectChangeEvent<string>) => {
|
||||
@@ -176,7 +189,10 @@ const GraphSliceFrontend: FC<{
|
||||
</FormControl>
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<Box component="div" id={plotDomId} sx={{ height: "450px" }} />
|
||||
<GraphContainer
|
||||
plotDomId={plotDomId}
|
||||
graphComponentState={graphComponentState}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
@@ -225,8 +241,7 @@ const plotSlice = (
|
||||
selectedParamTarget === null ||
|
||||
trials.length === 0
|
||||
) {
|
||||
plotly.react(plotDomId, [], layout)
|
||||
return
|
||||
return plotly.react(plotDomId, [], layout)
|
||||
}
|
||||
|
||||
const feasibleTrials: Trial[] = []
|
||||
@@ -305,5 +320,5 @@ const plotSlice = (
|
||||
automargin: true, // Otherwise the label is outside of the plot
|
||||
}
|
||||
}
|
||||
plotly.react(plotDomId, trace, layout)
|
||||
return plotly.react(plotDomId, trace, layout)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import { GraphComponentState } from "ts/types/optuna"
|
||||
|
||||
export const useGraphComponentState = () => {
|
||||
const [graphComponentState, setGraphComponentState] =
|
||||
useState<GraphComponentState>("componentWillMount")
|
||||
useEffect(() => {
|
||||
setGraphComponentState("componentDidMount")
|
||||
}, [])
|
||||
return {
|
||||
graphComponentState,
|
||||
notifyGraphDidRender: () => setGraphComponentState("graphDidRender"),
|
||||
}
|
||||
}
|
||||
@@ -196,3 +196,8 @@ export type PlotlyColorTheme = {
|
||||
dark: PlotlyColorThemeDark
|
||||
light: PlotlyColorThemeLight
|
||||
}
|
||||
|
||||
export type GraphComponentState =
|
||||
| "componentWillMount"
|
||||
| "componentDidMount"
|
||||
| "graphDidRender"
|
||||
|
||||
Reference in New Issue
Block a user