From 96a6362850e8db092a65b3bb792851bfeea46451 Mon Sep 17 00:00:00 2001 From: keisuke-umezawa Date: Mon, 9 Jan 2023 16:57:35 +0900 Subject: [PATCH] Use material ui --- optuna_dashboard/_app.py | 23 +++++++++-- optuna_dashboard/ts/action.ts | 16 ++++---- optuna_dashboard/ts/apiClient.ts | 12 ++++-- optuna_dashboard/ts/components/TrialTable.tsx | 38 +++++++++++-------- 4 files changed, 59 insertions(+), 30 deletions(-) diff --git a/optuna_dashboard/_app.py b/optuna_dashboard/_app.py index 9cb37cff..7b58fc54 100644 --- a/optuna_dashboard/_app.py +++ b/optuna_dashboard/_app.py @@ -31,7 +31,7 @@ from optuna.storages import BaseStorage from optuna.storages import RDBStorage from optuna.study import StudyDirection from optuna.study import StudySummary -from optuna.trial import FrozenTrial +from optuna.trial import FrozenTrial, TrialState from optuna.version import __version__ as optuna_ver from packaging import version @@ -413,12 +413,27 @@ def create_app(storage: BaseStorage, debug: bool = False) -> Bottle: @app.post("/api/studies///tell") @json_api_view - def tell_trial_value(study_id: int, trial_id: int) -> BottleViewReturn: + def tell_trial(study_id: int, trial_id: int) -> BottleViewReturn: + s = request.json.get("state", None) + v = request.json.get("value", None) + try: - value = float(request.json.get("value", None)) + value = float(v) if v is not None else v except ValueError: response.status = 400 # Bad request return {"reason": "You need to pass float castable value"} + + string2State = { + "Running": TrialState.RUNNING, + "Complete": TrialState.COMPLETE, + "Pruned": TrialState.PRUNED, + "Fail": TrialState.FAIL, + "Waiting": TrialState.WAITING, + } + if s not in string2State: + response.status = 400 # Bad request + return {"reason": f"You passed {s} as a state, which is not defined in Optuna."} + state = string2State[s] try: study_name = storage.get_study_name_from_id(study_id) @@ -429,7 +444,7 @@ def create_app(storage: BaseStorage, debug: bool = False) -> Bottle: study = optuna.load_study(storage=storage, study_name=study_name) try: - study.tell(trial_id, value) + study.tell(trial_id, values=value, state=state) except Exception as e: response.status = 400 # Bad request return {"reason": e.args} diff --git a/optuna_dashboard/ts/action.ts b/optuna_dashboard/ts/action.ts index 320eb52f..b8d77118 100644 --- a/optuna_dashboard/ts/action.ts +++ b/optuna_dashboard/ts/action.ts @@ -8,7 +8,7 @@ import { deleteStudyAPI, saveStudyNoteAPI, saveTrialNoteAPI, - saveTrialValueAPI, + tellTrialAPI, renameStudyAPI, } from "./apiClient" import { @@ -266,20 +266,22 @@ export const actionCreator = () => { }) } - const saveTrialValue = ( + const tellTrial = ( studyId: number, trialId: number, - value: string + state: TrialState, + value?: string ) => { - saveTrialValueAPI(studyId, trialId, value) + const message = value === undefined ? `id=${trialId}, state=${state}` : `id=${trialId}, state=${state}, value=${value}` + tellTrialAPI(studyId, trialId, state, value) .then(() => { - enqueueSnackbar(`Success to update trial value (id=${trialId}, value=${value})`, { + enqueueSnackbar(`Success to update trial (${message})`, { variant: "success", }) }) .catch((err) => { const reason = err.response?.data.reason - enqueueSnackbar(`Failed to update trial value (id=${trialId}, value=${value}). Reason: ${reason}`, { + enqueueSnackbar(`Failed to update trial (${message}). Reason: ${reason}`, { variant: "error", }) console.log(err) @@ -297,7 +299,7 @@ export const actionCreator = () => { saveGraphVisibility, saveStudyNote, saveTrialNote, - saveTrialValue, + tellTrial, } } diff --git a/optuna_dashboard/ts/apiClient.ts b/optuna_dashboard/ts/apiClient.ts index f3406e48..7ae68bd8 100644 --- a/optuna_dashboard/ts/apiClient.ts +++ b/optuna_dashboard/ts/apiClient.ts @@ -217,13 +217,19 @@ export const saveTrialNoteAPI = ( }) } -export const saveTrialValueAPI = ( +export const tellTrialAPI = ( studyId: number, trialId: number, - value: string, + state: TrialState, + value?: string ): Promise => { + const req: { [name: string]: string } = {state: state} + if (value !== undefined) { + req["value"] = value + } + return axiosInstance - .post(`/api/studies/${studyId}/${trialId}/tell`, {value: value}) + .post(`/api/studies/${studyId}/${trialId}/tell`, req) .then((res) => { return }) diff --git a/optuna_dashboard/ts/components/TrialTable.tsx b/optuna_dashboard/ts/components/TrialTable.tsx index ed05a7e3..6c547961 100644 --- a/optuna_dashboard/ts/components/TrialTable.tsx +++ b/optuna_dashboard/ts/components/TrialTable.tsx @@ -1,5 +1,5 @@ -import React, { ChangeEvent, FC, FormEvent, useState } from "react" -import { Typography, Grid, Box, IconButton } from "@mui/material" +import React, { ChangeEvent, FC, FormEvent, MouseEvent, useState } from "react" +import { Typography, Grid, Box, Button, IconButton, TextField } from "@mui/material" import LinkIcon from "@mui/icons-material/Link" import { DataGridColumn, DataGrid } from "./DataGrid" @@ -272,11 +272,16 @@ export const TrialTable: FC<{ e.preventDefault() const studyId = (studyDetail as StudyDetail).id const trialId = trials[index].number - action.saveTrialValue(studyId, trialId, value) + action.tellTrial(studyId, trialId, "Complete" as TrialState, value) } const handleChangeValue = (e: ChangeEvent): void => { setValue(e.target.value) } + const handleFailTrial = (e: MouseEvent): void => { + const studyId = (studyDetail as StudyDetail).id + const trialId = trials[index].number + action.tellTrial(studyId, trialId, "Fail" as TrialState) + } return ( @@ -308,22 +313,23 @@ export const TrialTable: FC<{ /> - + - Trial interactive operations + Trial tell operations -
-
-
- - -
-
- -
-
-
+
+ + + + + +
+