mirror of
https://github.com/wassname/optuna-dashboard.git
synced 2026-09-25 13:50:21 +08:00
Merge pull request #358 from c-bata/combine-history-intermediate-buttons
Add global state filters for History and IntermediateValue plots
This commit is contained in:
@@ -26,9 +26,13 @@ const plotDomId = "graph-history"
|
||||
|
||||
export const GraphHistory: FC<{
|
||||
study: StudyDetail | null
|
||||
}> = ({ study = null }) => {
|
||||
betaLogScale?: boolean
|
||||
betaIncludePruned?: boolean
|
||||
}> = ({ study, betaLogScale, betaIncludePruned }) => {
|
||||
const theme = useTheme()
|
||||
const [xAxis, setXAxis] = useState<string>("number")
|
||||
const [xAxis, setXAxis] = useState<
|
||||
"number" | "datetime_start" | "datetime_complete"
|
||||
>("number")
|
||||
const [logScale, setLogScale] = useState<boolean>(false)
|
||||
const [filterCompleteTrial, setFilterCompleteTrial] = useState<boolean>(false)
|
||||
const [filterPrunedTrial, setFilterPrunedTrial] = useState<boolean>(false)
|
||||
@@ -38,7 +42,7 @@ export const GraphHistory: FC<{
|
||||
study,
|
||||
[selected],
|
||||
filterCompleteTrial,
|
||||
filterPrunedTrial
|
||||
betaIncludePruned === undefined ? filterPrunedTrial : !betaIncludePruned
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -48,7 +52,7 @@ export const GraphHistory: FC<{
|
||||
study.directions,
|
||||
selected,
|
||||
xAxis,
|
||||
logScale,
|
||||
betaLogScale === undefined ? logScale : betaLogScale,
|
||||
theme.palette.mode
|
||||
)
|
||||
}
|
||||
@@ -57,9 +61,8 @@ export const GraphHistory: FC<{
|
||||
study?.directions,
|
||||
selected,
|
||||
logScale,
|
||||
betaLogScale,
|
||||
xAxis,
|
||||
filterPrunedTrial,
|
||||
filterCompleteTrial,
|
||||
theme.palette.mode,
|
||||
])
|
||||
|
||||
@@ -68,7 +71,13 @@ export const GraphHistory: FC<{
|
||||
}
|
||||
|
||||
const handleXAxisChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setXAxis(e.target.value)
|
||||
if (e.target.value === "number") {
|
||||
setXAxis("number")
|
||||
} else if (e.target.value === "datetime_start") {
|
||||
setXAxis("datetime_start")
|
||||
} else if (e.target.value === "datetime_complete") {
|
||||
setXAxis("datetime_complete")
|
||||
}
|
||||
}
|
||||
|
||||
const handleLogScaleChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
@@ -113,42 +122,46 @@ export const GraphHistory: FC<{
|
||||
</Select>
|
||||
</FormControl>
|
||||
) : null}
|
||||
<FormControl
|
||||
component="fieldset"
|
||||
sx={{ marginBottom: theme.spacing(2) }}
|
||||
>
|
||||
<FormLabel component="legend">Log y scale:</FormLabel>
|
||||
<Switch
|
||||
checked={logScale}
|
||||
onChange={handleLogScaleChange}
|
||||
value="enable"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl
|
||||
component="fieldset"
|
||||
sx={{ marginBottom: theme.spacing(2) }}
|
||||
>
|
||||
<FormLabel component="legend">Filter state:</FormLabel>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={!filterCompleteTrial}
|
||||
onChange={handleFilterCompleteChange}
|
||||
/>
|
||||
}
|
||||
label="Complete"
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={!filterPrunedTrial}
|
||||
disabled={!study?.has_intermediate_values}
|
||||
onChange={handleFilterPrunedChange}
|
||||
/>
|
||||
}
|
||||
label="Pruned"
|
||||
/>
|
||||
</FormControl>
|
||||
{betaLogScale === undefined ? (
|
||||
<FormControl
|
||||
component="fieldset"
|
||||
sx={{ marginBottom: theme.spacing(2) }}
|
||||
>
|
||||
<FormLabel component="legend">Log y scale:</FormLabel>
|
||||
<Switch
|
||||
checked={logScale}
|
||||
onChange={handleLogScaleChange}
|
||||
value="enable"
|
||||
/>
|
||||
</FormControl>
|
||||
) : null}
|
||||
{betaIncludePruned === undefined ? (
|
||||
<FormControl
|
||||
component="fieldset"
|
||||
sx={{ marginBottom: theme.spacing(2) }}
|
||||
>
|
||||
<FormLabel component="legend">Filter state:</FormLabel>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={!filterCompleteTrial}
|
||||
onChange={handleFilterCompleteChange}
|
||||
/>
|
||||
}
|
||||
label="Complete"
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={!filterPrunedTrial}
|
||||
disabled={!study?.has_intermediate_values}
|
||||
onChange={handleFilterPrunedChange}
|
||||
/>
|
||||
}
|
||||
label="Pruned"
|
||||
/>
|
||||
</FormControl>
|
||||
) : null}
|
||||
<FormControl
|
||||
component="fieldset"
|
||||
sx={{ marginBottom: theme.spacing(2) }}
|
||||
@@ -189,7 +202,7 @@ const plotHistory = (
|
||||
trials: Trial[],
|
||||
directions: StudyDirection[],
|
||||
target: Target,
|
||||
xAxis: string,
|
||||
xAxis: "number" | "datetime_start" | "datetime_complete",
|
||||
logScale: boolean,
|
||||
mode: string
|
||||
) => {
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
Card,
|
||||
CardContent,
|
||||
} from "@mui/material"
|
||||
import Grid2 from "@mui/material/Unstable_Grid2"
|
||||
|
||||
import { plotlyDarkTemplate } from "./PlotlyDarkMode"
|
||||
import { actionCreator } from "../action"
|
||||
@@ -47,16 +46,14 @@ export const GraphHyperparameterImportanceBeta: FC<{
|
||||
}, [nObjectives, importances, theme.palette.mode])
|
||||
|
||||
return (
|
||||
<Grid2 xs={6}>
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Typography variant="h6" sx={{ margin: "1em 0", fontWeight: 600 }}>
|
||||
Hyperparameter Importance
|
||||
</Typography>
|
||||
<Box id={plotDomId} sx={{ height: graphHeight }} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid2>
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Typography variant="h6" sx={{ margin: "1em 0", fontWeight: 600 }}>
|
||||
Hyperparameter Importance
|
||||
</Typography>
|
||||
<Box id={plotDomId} sx={{ height: graphHeight }} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,11 +9,42 @@ import {
|
||||
Grid,
|
||||
Typography,
|
||||
useTheme,
|
||||
CardContent,
|
||||
Card,
|
||||
} from "@mui/material"
|
||||
import { plotlyDarkTemplate } from "./PlotlyDarkMode"
|
||||
|
||||
const plotDomId = "graph-intermediate-values"
|
||||
|
||||
export const GraphIntermediateValuesBeta: FC<{
|
||||
trials: Trial[]
|
||||
includePruned: boolean
|
||||
logScale: boolean
|
||||
}> = ({ trials, includePruned, logScale }) => {
|
||||
const theme = useTheme()
|
||||
|
||||
useEffect(() => {
|
||||
plotIntermediateValue(
|
||||
trials,
|
||||
theme.palette.mode,
|
||||
false,
|
||||
!includePruned,
|
||||
logScale
|
||||
)
|
||||
}, [trials, theme.palette.mode, false, includePruned, logScale])
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Typography variant="h6" sx={{ margin: "1em 0", fontWeight: 600 }}>
|
||||
Intermediate values
|
||||
</Typography>
|
||||
<Box id={plotDomId} sx={{ height: "450px" }} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export const GraphIntermediateValues: FC<{
|
||||
trials: Trial[]
|
||||
}> = ({ trials = [] }) => {
|
||||
@@ -26,7 +57,8 @@ export const GraphIntermediateValues: FC<{
|
||||
trials,
|
||||
theme.palette.mode,
|
||||
filterCompleteTrial,
|
||||
filterPrunedTrial
|
||||
filterPrunedTrial,
|
||||
false
|
||||
)
|
||||
}, [trials, theme.palette.mode, filterCompleteTrial, filterPrunedTrial])
|
||||
|
||||
@@ -86,7 +118,8 @@ const plotIntermediateValue = (
|
||||
trials: Trial[],
|
||||
mode: string,
|
||||
filterCompleteTrial: boolean,
|
||||
filterPrunedTrial: boolean
|
||||
filterPrunedTrial: boolean,
|
||||
logScale: boolean
|
||||
) => {
|
||||
if (document.getElementById(plotDomId) === null) {
|
||||
return
|
||||
@@ -99,6 +132,14 @@ const plotIntermediateValue = (
|
||||
r: 50,
|
||||
b: 0,
|
||||
},
|
||||
yaxis: {
|
||||
title: "Objective Value",
|
||||
type: logScale ? "log" : "linear",
|
||||
},
|
||||
xaxis: {
|
||||
title: "Step",
|
||||
type: "linear",
|
||||
},
|
||||
template: mode === "dark" ? plotlyDarkTemplate : {},
|
||||
}
|
||||
if (trials.length === 0) {
|
||||
|
||||
@@ -165,7 +165,7 @@ export const StudyDetail: FC<{
|
||||
}}
|
||||
>
|
||||
<CardContent>
|
||||
<GraphHistory study={studyDetail} />
|
||||
<GraphHistory study={studyDetail} isBeta={false} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : null}
|
||||
|
||||
@@ -13,28 +13,21 @@ import Grid2 from "@mui/material/Unstable_Grid2"
|
||||
import ChevronRightIcon from "@mui/icons-material/ChevronRight"
|
||||
import HomeIcon from "@mui/icons-material/Home"
|
||||
|
||||
import { GraphHistory } from "./GraphHistory"
|
||||
import { StudyNote } from "./Note"
|
||||
import { actionCreator } from "../action"
|
||||
import {
|
||||
reloadIntervalState,
|
||||
useStudyDetailValue,
|
||||
useStudyDirections,
|
||||
useStudyName,
|
||||
useStudySummaryValue,
|
||||
} from "../state"
|
||||
import { TrialTable } from "./TrialTable"
|
||||
import { AppDrawer, PageId } from "./AppDrawer"
|
||||
import { GraphParallelCoordinate } from "./GraphParallelCoordinate"
|
||||
import { Contour } from "./GraphContour"
|
||||
import { GraphHyperparameterImportanceBeta } from "./GraphHyperparameterImportances"
|
||||
import { GraphSlice } from "./GraphSlice"
|
||||
import { GraphParetoFront } from "./GraphParetoFront"
|
||||
import { DataGrid, DataGridColumn } from "./DataGrid"
|
||||
import { GraphIntermediateValues } from "./GraphIntermediateValues"
|
||||
import { GraphEdfBeta } from "./GraphEdf"
|
||||
import { TrialList } from "./TrialList"
|
||||
import { BestTrialsCard } from "./BestTrialsCard"
|
||||
import { StudyHistory } from "./StudyHistory"
|
||||
|
||||
interface ParamTypes {
|
||||
studyId: string
|
||||
@@ -55,10 +48,7 @@ export const StudyDetailBeta: FC<{
|
||||
const studyId = useURLVars()
|
||||
const studyDetail = useStudyDetailValue(studyId)
|
||||
const reloadInterval = useRecoilValue<number>(reloadIntervalState)
|
||||
const studySummary = useStudySummaryValue(studyId)
|
||||
const directions = useStudyDirections(studyId)
|
||||
const studyName = useStudyName(studyId)
|
||||
const userAttrs = studySummary?.user_attrs || []
|
||||
|
||||
const title =
|
||||
studyName !== null ? `${studyName} (id=${studyId})` : `Study #${studyId}`
|
||||
@@ -77,78 +67,9 @@ export const StudyDetailBeta: FC<{
|
||||
return () => clearInterval(intervalId)
|
||||
}, [reloadInterval, studyDetail, page])
|
||||
|
||||
const userAttrColumns: DataGridColumn<Attribute>[] = [
|
||||
{ field: "key", label: "Key", sortable: true },
|
||||
{ field: "value", label: "Value", sortable: true },
|
||||
]
|
||||
const trials: Trial[] = studyDetail?.trials || []
|
||||
|
||||
let content = null
|
||||
if (page === "history") {
|
||||
content = (
|
||||
<Box sx={{ display: "flex", width: "100%", flexDirection: "column" }}>
|
||||
{directions !== null && directions.length > 1 ? (
|
||||
<Card sx={{ margin: theme.spacing(2) }}>
|
||||
<CardContent>
|
||||
<GraphParetoFront study={studyDetail} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : null}
|
||||
<Card
|
||||
sx={{
|
||||
margin: theme.spacing(2),
|
||||
}}
|
||||
>
|
||||
<CardContent>
|
||||
<GraphHistory study={studyDetail} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
{studyDetail !== null &&
|
||||
studyDetail.directions.length == 1 &&
|
||||
studyDetail.has_intermediate_values ? (
|
||||
<Card sx={{ margin: theme.spacing(2) }}>
|
||||
<CardContent>
|
||||
<GraphIntermediateValues trials={trials} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : null}
|
||||
<Grid2 container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
|
||||
<GraphHyperparameterImportanceBeta
|
||||
studyId={studyId}
|
||||
study={studyDetail}
|
||||
graphHeight="450px"
|
||||
/>
|
||||
<Grid2 xs={6} spacing={2}>
|
||||
<BestTrialsCard studyDetail={studyDetail} />
|
||||
</Grid2>
|
||||
<Grid2 xs={6}>
|
||||
<Card>
|
||||
<CardContent
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="h6"
|
||||
sx={{ margin: "1em 0", fontWeight: 600 }}
|
||||
>
|
||||
Study User Attributes
|
||||
</Typography>
|
||||
<DataGrid<Attribute>
|
||||
columns={userAttrColumns}
|
||||
rows={userAttrs}
|
||||
keyField={"key"}
|
||||
dense={true}
|
||||
initialRowsPerPage={5}
|
||||
rowsPerPageOption={[5, 10, { label: "All", value: -1 }]}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Box>
|
||||
)
|
||||
content = <StudyHistory studyId={studyId} />
|
||||
} else if (page === "analytics") {
|
||||
content = (
|
||||
<Box sx={{ display: "flex", width: "100%", flexDirection: "column" }}>
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
import React, { ChangeEvent, FC, useState } from "react"
|
||||
import {
|
||||
Box,
|
||||
Card,
|
||||
CardContent,
|
||||
FormControl,
|
||||
Switch,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from "@mui/material"
|
||||
import { GraphParetoFront } from "./GraphParetoFront"
|
||||
import { GraphHistory } from "./GraphHistory"
|
||||
import { GraphIntermediateValuesBeta } from "./GraphIntermediateValues"
|
||||
import Grid2 from "@mui/material/Unstable_Grid2"
|
||||
import { DataGrid, DataGridColumn } from "./DataGrid"
|
||||
import { GraphHyperparameterImportanceBeta } from "./GraphHyperparameterImportances"
|
||||
import { BestTrialsCard } from "./BestTrialsCard"
|
||||
import {
|
||||
useStudyDetailValue,
|
||||
useStudyDirections,
|
||||
useStudySummaryValue,
|
||||
} from "../state"
|
||||
import FormControlLabel from "@mui/material/FormControlLabel"
|
||||
|
||||
export const StudyHistory: FC<{ studyId: number }> = ({ studyId }) => {
|
||||
const theme = useTheme()
|
||||
const directions = useStudyDirections(studyId)
|
||||
const studySummary = useStudySummaryValue(studyId)
|
||||
const studyDetail = useStudyDetailValue(studyId)
|
||||
const [logScale, setLogScale] = useState<boolean>(false)
|
||||
const [includePruned, setIncludePruned] = useState<boolean>(true)
|
||||
|
||||
const handleLogScaleChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setLogScale(!logScale)
|
||||
}
|
||||
|
||||
const handleIncludePrunedChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setIncludePruned(!includePruned)
|
||||
}
|
||||
|
||||
const userAttrs = studySummary?.user_attrs || []
|
||||
const userAttrColumns: DataGridColumn<Attribute>[] = [
|
||||
{ field: "key", label: "Key", sortable: true },
|
||||
{ field: "value", label: "Value", sortable: true },
|
||||
]
|
||||
const trials: Trial[] = studyDetail?.trials || []
|
||||
return (
|
||||
<Box sx={{ display: "flex", width: "100%", flexDirection: "column" }}>
|
||||
<FormControl
|
||||
component="fieldset"
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
justifyContent: "flex-end",
|
||||
padding: theme.spacing(2),
|
||||
}}
|
||||
>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={logScale}
|
||||
onChange={handleLogScaleChange}
|
||||
value="enable"
|
||||
/>
|
||||
}
|
||||
label="Log y scale"
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={
|
||||
studyDetail
|
||||
? studyDetail.has_intermediate_values && includePruned
|
||||
: false
|
||||
}
|
||||
onChange={handleIncludePrunedChange}
|
||||
disabled={!studyDetail?.has_intermediate_values}
|
||||
value="enable"
|
||||
/>
|
||||
}
|
||||
label="Include PRUNED trials"
|
||||
/>
|
||||
</FormControl>
|
||||
{directions !== null && directions.length > 1 ? (
|
||||
<Card sx={{ margin: theme.spacing(2) }}>
|
||||
<CardContent>
|
||||
<GraphParetoFront study={studyDetail} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : null}
|
||||
<Card
|
||||
sx={{
|
||||
margin: theme.spacing(2),
|
||||
}}
|
||||
>
|
||||
<CardContent>
|
||||
<GraphHistory
|
||||
study={studyDetail}
|
||||
betaIncludePruned={includePruned}
|
||||
betaLogScale={logScale}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Grid2 container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
|
||||
{studyDetail !== null &&
|
||||
studyDetail.directions.length == 1 &&
|
||||
studyDetail.has_intermediate_values ? (
|
||||
<Grid2 xs={6}>
|
||||
<GraphIntermediateValuesBeta
|
||||
trials={trials}
|
||||
includePruned={includePruned}
|
||||
logScale={logScale}
|
||||
/>
|
||||
</Grid2>
|
||||
) : null}
|
||||
<Grid2 xs={6}>
|
||||
<GraphHyperparameterImportanceBeta
|
||||
studyId={studyId}
|
||||
study={studyDetail}
|
||||
graphHeight="450px"
|
||||
/>
|
||||
</Grid2>
|
||||
<Grid2 xs={6} spacing={2}>
|
||||
<BestTrialsCard studyDetail={studyDetail} />
|
||||
</Grid2>
|
||||
<Grid2 xs={6}>
|
||||
<Card>
|
||||
<CardContent
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="h6"
|
||||
sx={{ margin: "1em 0", fontWeight: 600 }}
|
||||
>
|
||||
Study User Attributes
|
||||
</Typography>
|
||||
<DataGrid<Attribute>
|
||||
columns={userAttrColumns}
|
||||
rows={userAttrs}
|
||||
keyField={"key"}
|
||||
dense={true}
|
||||
initialRowsPerPage={5}
|
||||
rowsPerPageOption={[5, 10, { label: "All", value: -1 }]}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user