From 02917ab3e5af4279d5c71fbc4c1145074dda32d3 Mon Sep 17 00:00:00 2001 From: hrntsm Date: Fri, 22 Sep 2023 21:05:12 +0900 Subject: [PATCH 01/38] Add redirect to pareto front --- .../ts/components/GraphParetoFront.tsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index abcf667d..0e3f1daa 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -35,6 +35,21 @@ export const GraphParetoFront: FC<{ useEffect(() => { if (study != null) { plotParetoFront(study, objectiveXId, objectiveYId, theme.palette.mode) + const element = document.getElementById(plotDomId) + if (element != null) { + // @ts-ignore + element.on("plotly_click", function (data) { + const plotTextInfo = JSON.parse( + data.points[0].text.replace(/
/g, "") + ) + const link =URL_PREFIX + `/studies/${study.id}}/trials?numbers=${plotTextInfo.number}` + window.location.href = link + }) + return () => { + // @ts-ignore + element.removeAllListeners("plotly_click") + } + } } }, [study, objectiveXId, objectiveYId, theme.palette.mode]) From 186f7ac95201de6cf6ccc8c60e9d9cd84dafd54e Mon Sep 17 00:00:00 2001 From: hrntsm Date: Fri, 22 Sep 2023 21:16:33 +0900 Subject: [PATCH 02/38] Add redirect to history --- optuna_dashboard/ts/components/GraphHistory.tsx | 15 +++++++++++++++ .../ts/components/GraphParetoFront.tsx | 4 +++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/optuna_dashboard/ts/components/GraphHistory.tsx b/optuna_dashboard/ts/components/GraphHistory.tsx index 280c02fc..d79afa70 100644 --- a/optuna_dashboard/ts/components/GraphHistory.tsx +++ b/optuna_dashboard/ts/components/GraphHistory.tsx @@ -69,6 +69,21 @@ export const GraphHistory: FC<{ theme.palette.mode, markerSize ) + const element = document.getElementById(plotDomId) + if (element != null && studies.length === 1) { + // @ts-ignore + element.on("plotly_click", function (data) { + const link = + URL_PREFIX + + `/studies/${studies[0].id}}/trials?numbers=${data.points[0].x}` + console.log(link) + window.location.href = link + }) + return () => { + // @ts-ignore + element.removeAllListeners("plotly_click") + } + } }, [studies, selected, logScale, xAxis, theme.palette.mode, markerSize]) const handleObjectiveChange = (event: SelectChangeEvent) => { diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index 0e3f1daa..b73a49cb 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -42,7 +42,9 @@ export const GraphParetoFront: FC<{ const plotTextInfo = JSON.parse( data.points[0].text.replace(/
/g, "") ) - const link =URL_PREFIX + `/studies/${study.id}}/trials?numbers=${plotTextInfo.number}` + const link = + URL_PREFIX + + `/studies/${study.id}}/trials?numbers=${plotTextInfo.number}` window.location.href = link }) return () => { From 3e822307f97b22c73bf8ac73f05a27f1ccd07701 Mon Sep 17 00:00:00 2001 From: hrntsm Date: Fri, 22 Sep 2023 21:17:24 +0900 Subject: [PATCH 03/38] Remove console.log output --- optuna_dashboard/ts/components/GraphHistory.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/optuna_dashboard/ts/components/GraphHistory.tsx b/optuna_dashboard/ts/components/GraphHistory.tsx index d79afa70..4eb5588d 100644 --- a/optuna_dashboard/ts/components/GraphHistory.tsx +++ b/optuna_dashboard/ts/components/GraphHistory.tsx @@ -76,7 +76,6 @@ export const GraphHistory: FC<{ const link = URL_PREFIX + `/studies/${studies[0].id}}/trials?numbers=${data.points[0].x}` - console.log(link) window.location.href = link }) return () => { From 9d510fb64254b45fe4eacc9515f0563b742b233a Mon Sep 17 00:00:00 2001 From: hrntsm Date: Sun, 24 Sep 2023 21:43:28 +0900 Subject: [PATCH 04/38] Remove redundant '}' --- optuna_dashboard/ts/components/GraphHistory.tsx | 2 +- optuna_dashboard/ts/components/GraphParetoFront.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphHistory.tsx b/optuna_dashboard/ts/components/GraphHistory.tsx index 4eb5588d..52c3fceb 100644 --- a/optuna_dashboard/ts/components/GraphHistory.tsx +++ b/optuna_dashboard/ts/components/GraphHistory.tsx @@ -75,7 +75,7 @@ export const GraphHistory: FC<{ element.on("plotly_click", function (data) { const link = URL_PREFIX + - `/studies/${studies[0].id}}/trials?numbers=${data.points[0].x}` + `/studies/${studies[0].id}/trials?numbers=${data.points[0].x}` window.location.href = link }) return () => { diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index b73a49cb..35de2315 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -44,7 +44,7 @@ export const GraphParetoFront: FC<{ ) const link = URL_PREFIX + - `/studies/${study.id}}/trials?numbers=${plotTextInfo.number}` + `/studies/${study.id}/trials?numbers=${plotTextInfo.number}` window.location.href = link }) return () => { From 37f0709bc85ac3949898ea6b28b27d2d81fa828c Mon Sep 17 00:00:00 2001 From: hrntsm Date: Sun, 24 Sep 2023 21:53:34 +0900 Subject: [PATCH 05/38] Update redirect to work with multi studies --- optuna_dashboard/ts/components/GraphHistory.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphHistory.tsx b/optuna_dashboard/ts/components/GraphHistory.tsx index 52c3fceb..da09fb60 100644 --- a/optuna_dashboard/ts/components/GraphHistory.tsx +++ b/optuna_dashboard/ts/components/GraphHistory.tsx @@ -70,12 +70,14 @@ export const GraphHistory: FC<{ markerSize ) const element = document.getElementById(plotDomId) - if (element != null && studies.length === 1) { + if (element != null && studies.length >= 1) { // @ts-ignore element.on("plotly_click", function (data) { const link = URL_PREFIX + - `/studies/${studies[0].id}/trials?numbers=${data.points[0].x}` + `/studies/${ + studies[Math.floor(data.points[0].curveNumber / 2)].id + }/trials?numbers=${data.points[0].x}` window.location.href = link }) return () => { From 475eaa78e188045253ad07d60e5eb45e2bf0a87b Mon Sep 17 00:00:00 2001 From: hrntsm Date: Sun, 24 Sep 2023 21:56:23 +0900 Subject: [PATCH 06/38] Update to not redirect when selecting lines --- optuna_dashboard/ts/components/GraphHistory.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphHistory.tsx b/optuna_dashboard/ts/components/GraphHistory.tsx index da09fb60..65f845a2 100644 --- a/optuna_dashboard/ts/components/GraphHistory.tsx +++ b/optuna_dashboard/ts/components/GraphHistory.tsx @@ -73,12 +73,14 @@ export const GraphHistory: FC<{ if (element != null && studies.length >= 1) { // @ts-ignore element.on("plotly_click", function (data) { - const link = - URL_PREFIX + - `/studies/${ - studies[Math.floor(data.points[0].curveNumber / 2)].id - }/trials?numbers=${data.points[0].x}` - window.location.href = link + if (data.points[0].data.mode !== "lines") { + const link = + URL_PREFIX + + `/studies/${ + studies[Math.floor(data.points[0].curveNumber / 2)].id + }/trials?numbers=${data.points[0].x}` + window.location.href = link + } }) return () => { // @ts-ignore From d1d5f3c65159c3d9aa521f13cccd2dc84b8822f2 Mon Sep 17 00:00:00 2001 From: hrntsm Date: Fri, 29 Sep 2023 13:06:38 +0900 Subject: [PATCH 07/38] Update to use useNavigate --- optuna_dashboard/ts/components/GraphHistory.tsx | 12 +++++++----- optuna_dashboard/ts/components/GraphParetoFront.tsx | 8 +++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphHistory.tsx b/optuna_dashboard/ts/components/GraphHistory.tsx index 65f845a2..99db2524 100644 --- a/optuna_dashboard/ts/components/GraphHistory.tsx +++ b/optuna_dashboard/ts/components/GraphHistory.tsx @@ -21,6 +21,7 @@ import { Target, useObjectiveAndUserAttrTargetsFromStudies, } from "../trialFilter" +import { useNavigate } from "react-router-dom" const plotDomId = "graph-history" @@ -37,6 +38,7 @@ export const GraphHistory: FC<{ includePruned: boolean }> = ({ studies, logScale, includePruned }) => { const theme = useTheme() + const navigate = useNavigate() const [xAxis, setXAxis] = useState< "number" | "datetime_start" | "datetime_complete" >("number") @@ -74,12 +76,12 @@ export const GraphHistory: FC<{ // @ts-ignore element.on("plotly_click", function (data) { if (data.points[0].data.mode !== "lines") { - const link = + navigate( URL_PREFIX + - `/studies/${ - studies[Math.floor(data.points[0].curveNumber / 2)].id - }/trials?numbers=${data.points[0].x}` - window.location.href = link + `/studies/${ + studies[Math.floor(data.points[0].curveNumber / 2)].id + }/trials?numbers=${data.points[0].x}` + ) } }) return () => { diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index 35de2315..893d589d 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -13,6 +13,7 @@ import { } from "@mui/material" import { plotlyDarkTemplate } from "./PlotlyDarkMode" import { makeHovertext } from "../graphUtil" +import { useNavigate } from "react-router-dom" const plotDomId = "graph-pareto-front" @@ -20,6 +21,7 @@ export const GraphParetoFront: FC<{ study: StudyDetail | null }> = ({ study = null }) => { const theme = useTheme() + const navigate = useNavigate() const [objectiveXId, setObjectiveXId] = useState(0) const [objectiveYId, setObjectiveYId] = useState(1) const objectiveNames: string[] = study?.objective_names || [] @@ -42,10 +44,10 @@ export const GraphParetoFront: FC<{ const plotTextInfo = JSON.parse( data.points[0].text.replace(/
/g, "") ) - const link = + navigate( URL_PREFIX + - `/studies/${study.id}/trials?numbers=${plotTextInfo.number}` - window.location.href = link + `/studies/${study.id}/trials?numbers=${plotTextInfo.number}` + ) }) return () => { // @ts-ignore From 563775e904d585ab736f9112e7049e7010fdefae Mon Sep 17 00:00:00 2001 From: hrntsm Date: Fri, 29 Sep 2023 14:19:34 +0900 Subject: [PATCH 08/38] Fix infeasible point redirect --- .../ts/components/GraphHistory.tsx | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphHistory.tsx b/optuna_dashboard/ts/components/GraphHistory.tsx index 99db2524..b717183a 100644 --- a/optuna_dashboard/ts/components/GraphHistory.tsx +++ b/optuna_dashboard/ts/components/GraphHistory.tsx @@ -76,11 +76,26 @@ export const GraphHistory: FC<{ // @ts-ignore element.on("plotly_click", function (data) { if (data.points[0].data.mode !== "lines") { + let studyId = 1 + if (data.points[0].data.name.includes("Infeasible Trial of")) { + const studyInfo: { id: number; name: string }[] = [] + studies.forEach((study) => { + studyInfo.push({ id: study.id, name: study.name }) + }) + const dataPointStudyName = data.points[0].data.name.replace( + "Infeasible Trial of ", + "" + ) + const targetId = studyInfo.find((s) => s.name === dataPointStudyName)?.id + if (targetId !== undefined) { + studyId = targetId + } + } else { + studyId = studies[Math.floor(data.points[0].curveNumber / 2)].id + } navigate( URL_PREFIX + - `/studies/${ - studies[Math.floor(data.points[0].curveNumber / 2)].id - }/trials?numbers=${data.points[0].x}` + `/studies/${studyId}/trials?numbers=${data.points[0].x}` ) } }) From db2f6310c85f98f9f288f6e50ab7811b860f0e7f Mon Sep 17 00:00:00 2001 From: hrntsm Date: Fri, 29 Sep 2023 14:37:40 +0900 Subject: [PATCH 09/38] Apply formatter --- optuna_dashboard/ts/components/GraphHistory.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/optuna_dashboard/ts/components/GraphHistory.tsx b/optuna_dashboard/ts/components/GraphHistory.tsx index b717183a..a2b58c14 100644 --- a/optuna_dashboard/ts/components/GraphHistory.tsx +++ b/optuna_dashboard/ts/components/GraphHistory.tsx @@ -86,7 +86,9 @@ export const GraphHistory: FC<{ "Infeasible Trial of ", "" ) - const targetId = studyInfo.find((s) => s.name === dataPointStudyName)?.id + const targetId = studyInfo.find( + (s) => s.name === dataPointStudyName + )?.id if (targetId !== undefined) { studyId = targetId } From a7429318f3231ae6713cd7d9954a5c8e9a1b8548 Mon Sep 17 00:00:00 2001 From: nabenabe0928 Date: Fri, 1 Dec 2023 10:22:11 +0100 Subject: [PATCH 10/38] Limit the maximum number of trials to be used for one update More specifically, this PR makes the following changes: 1. Add query param for limit, 2. Update studyDetails only if there is no study with the specified study_id or the fetched trials has a positive length, 3. Shorten the waiting interval when there is a leftover in the server side, and 4. Adapt the flake8 setup to the Optuna repo. --- optuna_dashboard/_app.py | 25 ++++++++++++------- optuna_dashboard/_serializer.py | 2 ++ optuna_dashboard/ts/action.ts | 14 ++++++++--- optuna_dashboard/ts/apiClient.ts | 6 ++++- .../ts/components/StudyDetail.tsx | 8 +++++- optuna_dashboard/ts/state.ts | 5 ++++ optuna_dashboard/ts/types/index.d.ts | 1 + python_tests/test_serializers.py | 4 +-- setup.cfg | 3 +++ 9 files changed, 52 insertions(+), 16 deletions(-) diff --git a/optuna_dashboard/_app.py b/optuna_dashboard/_app.py index ead27188..1dd05854 100644 --- a/optuna_dashboard/_app.py +++ b/optuna_dashboard/_app.py @@ -191,14 +191,19 @@ def create_app( @app.get("/api/studies/") @json_api_view def get_study_detail(study_id: int) -> dict[str, Any]: - try: - after = int(request.params["after"]) - assert after >= 0 - except AssertionError: - response.status = 400 # Bad parameter - return {"reason": "`after` should be larger or equal 0."} - except KeyError: - after = 0 + query_params = dict(after=0, limit=1000) + for query_key in query_params: + try: + query_params[query_key] = int(request.params[query_key]) + assert query_params[query_key] >= 0 + except AssertionError: + response.status = 400 # Bad parameter + return {"reason": f"`{query_key}` should be larger than or equal to 0."} + except KeyError: + # Use the default parameter defined in query_params. + pass + + after, limit = query_params["after"], query_params["limit"] summary = get_study_summary(storage, study_id) if summary is None: response.status = 404 # Not found @@ -229,16 +234,18 @@ def create_app( plotly_graph_objects = get_plotly_graph_objects(system_attrs) skipped_trial_ids = get_skipped_trial_ids(system_attrs) skipped_trial_numbers = [t.number for t in trials if t._trial_id in skipped_trial_ids] + fetched_trials_partially = after + limit < len(trials) return serialize_study_detail( summary, best_trials, - trials[after:], + trials[after : after + limit], intersection, union, union_user_attrs, has_intermediate_values, plotly_graph_objects, skipped_trial_numbers, + fetched_trials_partially, ) @app.get("/api/studies//param_importances") diff --git a/optuna_dashboard/_serializer.py b/optuna_dashboard/_serializer.py index 7030abec..3bc659c3 100644 --- a/optuna_dashboard/_serializer.py +++ b/optuna_dashboard/_serializer.py @@ -141,11 +141,13 @@ def serialize_study_detail( has_intermediate_values: bool, plotly_graph_objects: dict[str, str], skipped_trial_numbers: list[int], + fetched_trials_partially: bool, ) -> dict[str, Any]: serialized: dict[str, Any] = { "name": summary.study_name, "directions": [d.name.lower() for d in summary.directions], "user_attrs": serialize_attrs(summary.user_attrs), + "fetched_trials_partially": fetched_trials_partially, } system_attrs = getattr(summary, "system_attrs", {}) serialized["artifacts"] = list_study_artifacts(system_attrs) diff --git a/optuna_dashboard/ts/action.ts b/optuna_dashboard/ts/action.ts index 10fe43bc..3947a0ee 100644 --- a/optuna_dashboard/ts/action.ts +++ b/optuna_dashboard/ts/action.ts @@ -27,6 +27,7 @@ import { studySummariesState, paramImportanceState, isFileUploading, + isTrialLeftInCache, artifactIsAvailable, reloadIntervalState, trialsUpdatingState, @@ -46,6 +47,7 @@ export const actionCreator = () => { const setUploading = useSetRecoilState(isFileUploading) const setTrialsUpdating = useSetRecoilState(trialsUpdatingState) const setArtifactIsAvailable = useSetRecoilState(artifactIsAvailable) + const setIsTrialLeftInCache = useSetRecoilState(isTrialLeftInCache) const setStudyDetailState = (studyId: number, study: StudyDetail) => { setStudyDetails((prevVal) => { @@ -233,6 +235,7 @@ export const actionCreator = () => { const updateStudyDetail = (studyId: number) => { let nLocalFixedTrials = 0 + let nMaximumTrialsAtOnce = 1000 if (studyId in studyDetails) { const currentTrials = studyDetails[studyId].trials const firstUpdatable = currentTrials.findIndex((trial) => @@ -240,15 +243,20 @@ export const actionCreator = () => { ) nLocalFixedTrials = firstUpdatable === -1 ? currentTrials.length : firstUpdatable + nMaximumTrialsAtOnce = 2000 } - getStudyDetailAPI(studyId, nLocalFixedTrials) + getStudyDetailAPI(studyId, nLocalFixedTrials, nMaximumTrialsAtOnce) .then((study) => { const currentFixedTrials = studyId in studyDetails ? studyDetails[studyId].trials.slice(0, nLocalFixedTrials) : [] - study.trials = currentFixedTrials.concat(study.trials) - setStudyDetailState(studyId, study) + if (study.trials.length !== 0 || !(studyId in studyDetails)) { + // Update trials only if necessary. The second condition is for study with no trials. + study.trials = currentFixedTrials.concat(study.trials) + setStudyDetailState(studyId, study) + setIsTrialLeftInCache(study.fetched_trials_partially) + } }) .catch((err) => { const reason = err.response?.data.reason diff --git a/optuna_dashboard/ts/apiClient.ts b/optuna_dashboard/ts/apiClient.ts index f42d20de..ec80056d 100644 --- a/optuna_dashboard/ts/apiClient.ts +++ b/optuna_dashboard/ts/apiClient.ts @@ -102,16 +102,19 @@ interface StudyDetailResponse { artifacts: Artifact[] feedback_component_type: FeedbackComponentType skipped_trial_numbers?: number[] + fetched_trials_partially: boolean } export const getStudyDetailAPI = ( studyId: number, - nLocalTrials: number + nLocalTrials: number, + nMaximumTrialsAtOnce: number ): Promise => { return axiosInstance .get(`/api/studies/${studyId}`, { params: { after: nLocalTrials, + limit: nMaximumTrialsAtOnce, }, }) .then((res) => { @@ -145,6 +148,7 @@ export const getStudyDetailAPI = ( plotly_graph_objects: res.data.plotly_graph_objects, artifacts: res.data.artifacts, skipped_trial_numbers: res.data.skipped_trial_numbers ?? [], + fetched_trials_partially: res.data.fetched_trials_partially, } }) } diff --git a/optuna_dashboard/ts/components/StudyDetail.tsx b/optuna_dashboard/ts/components/StudyDetail.tsx index 2f56ec8b..1f2823dd 100644 --- a/optuna_dashboard/ts/components/StudyDetail.tsx +++ b/optuna_dashboard/ts/components/StudyDetail.tsx @@ -17,6 +17,7 @@ import DownloadIcon from "@mui/icons-material/Download" import { StudyNote } from "./Note" import { actionCreator } from "../action" import { + isTrialLeftInCache, reloadIntervalState, useStudyDetailValue, useStudyIsPreferential, @@ -57,6 +58,7 @@ export const StudyDetail: FC<{ const reloadInterval = useRecoilValue(reloadIntervalState) const studyName = useStudyName(studyId) const isPreferential = useStudyIsPreferential(studyId) + const isTrialLeft = useRecoilValue(isTrialLeftInCache) const title = studyName !== null ? `${studyName} (id=${studyId})` : `Study #${studyId}` @@ -73,9 +75,13 @@ export const StudyDetail: FC<{ const nTrials = studyDetail ? studyDetail.trials.length : 0 let interval = reloadInterval * 1000 + // If trials are left in cache, we collect them quickly. // For Human-in-the-loop Optimization, the interval is set to 2 seconds // when the number of trials is small, and the page is "trialList" or top page of preferential. - if ( + if (isTrialLeft) { + // Too short time is frustrating because the page freezes until the rendering is done. + interval = 3000 + } else if ( (!isPreferential && page === "trialList") || (isPreferential && page === "top") ) { diff --git a/optuna_dashboard/ts/state.ts b/optuna_dashboard/ts/state.ts index b1f60654..7825311b 100644 --- a/optuna_dashboard/ts/state.ts +++ b/optuna_dashboard/ts/state.ts @@ -33,6 +33,11 @@ export const drawerOpenState = atom({ default: false, }) +export const isTrialLeftInCache = atom({ + key: "isTrialLeftInCache", + default: false, +}) + export const isFileUploading = atom({ key: "isFileUploading", default: false, diff --git a/optuna_dashboard/ts/types/index.d.ts b/optuna_dashboard/ts/types/index.d.ts index 67182ff8..b1ed1bb7 100644 --- a/optuna_dashboard/ts/types/index.d.ts +++ b/optuna_dashboard/ts/types/index.d.ts @@ -220,6 +220,7 @@ type StudyDetail = { plotly_graph_objects: PlotlyGraphObject[] artifacts: Artifact[] skipped_trial_numbers: number[] + fetched_trials_partially: boolean } type StudyDetails = { diff --git a/python_tests/test_serializers.py b/python_tests/test_serializers.py index d1bdf59b..1f52d926 100644 --- a/python_tests/test_serializers.py +++ b/python_tests/test_serializers.py @@ -61,7 +61,7 @@ def test_get_study_detail_is_preferential() -> None: study_summary = study_summaries[0] study_detail = serialize_study_detail( - study_summary, [], study.trials, [], [], [], False, {}, [] + study_summary, [], study.trials, [], [], [], False, {}, [], False ) assert study_detail["is_preferential"] @@ -74,7 +74,7 @@ def test_get_study_detail_is_not_preferential() -> None: study_summary = study_summaries[0] study_detail = serialize_study_detail( - study_summary, [], study.trials, [], [], [], False, {}, [] + study_summary, [], study.trials, [], [], [], False, {}, [], False ) assert not study_detail["is_preferential"] diff --git a/setup.cfg b/setup.cfg index 93d9ad56..1eabbdce 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,4 +1,7 @@ [flake8] +ignore = + E203 + W503 max-line-length = 99 statistics = True exclude = venv,build From 5bd1d5538a9464eb42e010056ca9126840c057bf Mon Sep 17 00:00:00 2001 From: nabenabe0928 Date: Mon, 25 Dec 2023 08:06:31 +0100 Subject: [PATCH 11/38] Replace the first load n_trials with 2000 --- optuna_dashboard/ts/action.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/optuna_dashboard/ts/action.ts b/optuna_dashboard/ts/action.ts index 3947a0ee..961aadb7 100644 --- a/optuna_dashboard/ts/action.ts +++ b/optuna_dashboard/ts/action.ts @@ -235,7 +235,7 @@ export const actionCreator = () => { const updateStudyDetail = (studyId: number) => { let nLocalFixedTrials = 0 - let nMaximumTrialsAtOnce = 1000 + let nMaximumTrialsAtOnce = 2000 if (studyId in studyDetails) { const currentTrials = studyDetails[studyId].trials const firstUpdatable = currentTrials.findIndex((trial) => @@ -243,7 +243,6 @@ export const actionCreator = () => { ) nLocalFixedTrials = firstUpdatable === -1 ? currentTrials.length : firstUpdatable - nMaximumTrialsAtOnce = 2000 } getStudyDetailAPI(studyId, nLocalFixedTrials, nMaximumTrialsAtOnce) .then((study) => { From bef9fb9e2701087a2cc1925e0c4041b9cea3ddbb Mon Sep 17 00:00:00 2001 From: nabenabe0928 Date: Mon, 25 Dec 2023 08:10:13 +0100 Subject: [PATCH 12/38] Add a comment line for the default query values --- optuna_dashboard/_app.py | 1 + 1 file changed, 1 insertion(+) diff --git a/optuna_dashboard/_app.py b/optuna_dashboard/_app.py index 1dd05854..a0be6770 100644 --- a/optuna_dashboard/_app.py +++ b/optuna_dashboard/_app.py @@ -191,6 +191,7 @@ def create_app( @app.get("/api/studies/") @json_api_view def get_study_detail(study_id: int) -> dict[str, Any]: + # Use the following default values if not specified in request.params. query_params = dict(after=0, limit=1000) for query_key in query_params: try: From 646bc7497eba683476a815584d561f8d90c80d0a Mon Sep 17 00:00:00 2001 From: nabenabe0928 Date: Mon, 25 Dec 2023 08:16:09 +0100 Subject: [PATCH 13/38] Rename isTrialLeftInCache with FetchedTrialsPartially for uniformity --- optuna_dashboard/ts/action.ts | 10 ++++++---- optuna_dashboard/ts/components/StudyDetail.tsx | 8 +++++--- optuna_dashboard/ts/state.ts | 4 ++-- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/optuna_dashboard/ts/action.ts b/optuna_dashboard/ts/action.ts index 961aadb7..c2d3cc31 100644 --- a/optuna_dashboard/ts/action.ts +++ b/optuna_dashboard/ts/action.ts @@ -27,7 +27,7 @@ import { studySummariesState, paramImportanceState, isFileUploading, - isTrialLeftInCache, + fetchedTrialsPartiallyState, artifactIsAvailable, reloadIntervalState, trialsUpdatingState, @@ -47,7 +47,9 @@ export const actionCreator = () => { const setUploading = useSetRecoilState(isFileUploading) const setTrialsUpdating = useSetRecoilState(trialsUpdatingState) const setArtifactIsAvailable = useSetRecoilState(artifactIsAvailable) - const setIsTrialLeftInCache = useSetRecoilState(isTrialLeftInCache) + const setFetchedTrialsPartially = useSetRecoilState( + fetchedTrialsPartiallyState + ) const setStudyDetailState = (studyId: number, study: StudyDetail) => { setStudyDetails((prevVal) => { @@ -235,7 +237,7 @@ export const actionCreator = () => { const updateStudyDetail = (studyId: number) => { let nLocalFixedTrials = 0 - let nMaximumTrialsAtOnce = 2000 + const nMaximumTrialsAtOnce = 2000 if (studyId in studyDetails) { const currentTrials = studyDetails[studyId].trials const firstUpdatable = currentTrials.findIndex((trial) => @@ -254,7 +256,7 @@ export const actionCreator = () => { // Update trials only if necessary. The second condition is for study with no trials. study.trials = currentFixedTrials.concat(study.trials) setStudyDetailState(studyId, study) - setIsTrialLeftInCache(study.fetched_trials_partially) + setFetchedTrialsPartially(study.fetched_trials_partially) } }) .catch((err) => { diff --git a/optuna_dashboard/ts/components/StudyDetail.tsx b/optuna_dashboard/ts/components/StudyDetail.tsx index 1f2823dd..321fcafa 100644 --- a/optuna_dashboard/ts/components/StudyDetail.tsx +++ b/optuna_dashboard/ts/components/StudyDetail.tsx @@ -17,7 +17,7 @@ import DownloadIcon from "@mui/icons-material/Download" import { StudyNote } from "./Note" import { actionCreator } from "../action" import { - isTrialLeftInCache, + fetchedTrialsPartiallyState, reloadIntervalState, useStudyDetailValue, useStudyIsPreferential, @@ -58,7 +58,9 @@ export const StudyDetail: FC<{ const reloadInterval = useRecoilValue(reloadIntervalState) const studyName = useStudyName(studyId) const isPreferential = useStudyIsPreferential(studyId) - const isTrialLeft = useRecoilValue(isTrialLeftInCache) + const fetchedTrialsPartially = useRecoilValue( + fetchedTrialsPartiallyState + ) const title = studyName !== null ? `${studyName} (id=${studyId})` : `Study #${studyId}` @@ -78,7 +80,7 @@ export const StudyDetail: FC<{ // If trials are left in cache, we collect them quickly. // For Human-in-the-loop Optimization, the interval is set to 2 seconds // when the number of trials is small, and the page is "trialList" or top page of preferential. - if (isTrialLeft) { + if (fetchedTrialsPartially) { // Too short time is frustrating because the page freezes until the rendering is done. interval = 3000 } else if ( diff --git a/optuna_dashboard/ts/state.ts b/optuna_dashboard/ts/state.ts index 7825311b..7b64d0d4 100644 --- a/optuna_dashboard/ts/state.ts +++ b/optuna_dashboard/ts/state.ts @@ -33,8 +33,8 @@ export const drawerOpenState = atom({ default: false, }) -export const isTrialLeftInCache = atom({ - key: "isTrialLeftInCache", +export const fetchedTrialsPartiallyState = atom({ + key: "fetchedTrialsPartially", default: false, }) From 967f6ceb553293bd5b19bbc1441c3b8de6c27c4b Mon Sep 17 00:00:00 2001 From: nabenabe0928 Date: Mon, 25 Dec 2023 10:27:12 +0100 Subject: [PATCH 14/38] Address the umezawa's comment --- optuna_dashboard/ts/action.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/optuna_dashboard/ts/action.ts b/optuna_dashboard/ts/action.ts index c2d3cc31..a54e09ea 100644 --- a/optuna_dashboard/ts/action.ts +++ b/optuna_dashboard/ts/action.ts @@ -248,16 +248,18 @@ export const actionCreator = () => { } getStudyDetailAPI(studyId, nLocalFixedTrials, nMaximumTrialsAtOnce) .then((study) => { + if (studyId in studyDetails && study.trials.length === 0) { + // Update trials only if necessary. + // NOTE: The first condition is for study with no trials. + return + } const currentFixedTrials = studyId in studyDetails ? studyDetails[studyId].trials.slice(0, nLocalFixedTrials) : [] - if (study.trials.length !== 0 || !(studyId in studyDetails)) { - // Update trials only if necessary. The second condition is for study with no trials. - study.trials = currentFixedTrials.concat(study.trials) - setStudyDetailState(studyId, study) - setFetchedTrialsPartially(study.fetched_trials_partially) - } + study.trials = currentFixedTrials.concat(study.trials) + setStudyDetailState(studyId, study) + setFetchedTrialsPartially(study.fetched_trials_partially) }) .catch((err) => { const reason = err.response?.data.reason From d04101fb769c171fb435789e1d0edaa96dc10063 Mon Sep 17 00:00:00 2001 From: nabenabe0928 Date: Tue, 26 Dec 2023 09:12:16 +0100 Subject: [PATCH 15/38] Add some tests --- python_tests/test_api.py | 73 +++++++++++++++------------------------- 1 file changed, 28 insertions(+), 45 deletions(-) diff --git a/python_tests/test_api.py b/python_tests/test_api.py index e7210710..ebe5a0ef 100644 --- a/python_tests/test_api.py +++ b/python_tests/test_api.py @@ -1,12 +1,14 @@ from __future__ import annotations import json +import pytest import sys from unittest import TestCase import optuna from optuna import get_all_study_summaries from optuna.study import StudyDirection +from optuna.trial import FrozenTrial from optuna_dashboard._app import create_app from optuna_dashboard._app import create_new_study from optuna_dashboard._note import note_str_key_prefix @@ -44,70 +46,51 @@ class APITestCase(TestCase): study_summaries = json.loads(body)["study_summaries"] self.assertEqual(len(study_summaries), 2) - def test_get_study_details_without_after_param(self) -> None: + def run_get_study_details( + self, queries: dict[str, str] | None = None, expected_status: int = 200, + ) -> tuple[int, list[FrozenTrial]]: study = optuna.create_study() study_id = study._study_id - study.optimize(objective, n_trials=2) + study.optimize(objective, n_trials=10) app = create_app(study._storage) status, _, body = send_request( app, f"/api/studies/{study_id}", "GET", + queries=queries, content_type="application/json", ) - self.assertEqual(status, 200) - all_trials = json.loads(body)["trials"] - self.assertEqual(len(all_trials), 2) + self.assertEqual(status, expected_status) + if expected_status == 400: + return [] + else: + return json.loads(body)["trials"] + + def test_get_study_details_without_after_param(self) -> None: + all_trials = self.run_get_study_details() + self.assertEqual(len(all_trials), 10) def test_get_study_details_with_after_param_partial(self) -> None: - study = optuna.create_study() - study_id = study._study_id - study.optimize(objective, n_trials=2) - app = create_app(study._storage) + all_trials = self.run_get_study_details({"after": "5"}) + self.assertEqual(len(all_trials), 5) - status, _, body = send_request( - app, - f"/api/studies/{study_id}", - "GET", - queries={"after": "1"}, - content_type="application/json", - ) - self.assertEqual(status, 200) - all_trials = json.loads(body)["trials"] - self.assertEqual(len(all_trials), 1) + def test_get_study_details_with_params(self) -> None: + for after in [0, 5, 9, 10]: + for limit in [1, 2, 5, 10]: + trials = self.run_get_study_details({"after": str(after), "limit": str(limit)}) + ans = list(range(after, min(10, after + limit))) + self.assertEqual([t["number"] for t in trials], ans) def test_get_study_details_with_after_param_full(self) -> None: - study = optuna.create_study() - study_id = study._study_id - study.optimize(objective, n_trials=2) - app = create_app(study._storage) - - status, _, body = send_request( - app, - f"/api/studies/{study_id}", - "GET", - queries={"after": "2"}, - content_type="application/json", - ) - self.assertEqual(status, 200) - all_trials = json.loads(body)["trials"] + all_trials = self.run_get_study_details({"after": "10"}) self.assertEqual(len(all_trials), 0) def test_get_study_details_with_after_param_illegal(self) -> None: - study = optuna.create_study() - study_id = study._study_id - study.optimize(objective, n_trials=2) - app = create_app(study._storage) + self.run_get_study_details({"after": "-1"}, expected_status=400) - status, _, body = send_request( - app, - f"/api/studies/{study_id}", - "GET", - queries={"after": "-1"}, - content_type="application/json", - ) - self.assertEqual(status, 400) + def test_get_study_details_with_limit_param_illegal(self) -> None: + self.run_get_study_details({"limit": "-1"}, expected_status=400) @pytest.mark.skipif(sys.version_info < (3, 8), reason="BoTorch dropped Python3.7 support") def test_get_best_trials_of_preferential_study(self) -> None: From a2cf3ebd54d3dbe2b23cd2bb4fbfc554f9b3cd41 Mon Sep 17 00:00:00 2001 From: nabenabe0928 Date: Tue, 26 Dec 2023 09:15:55 +0100 Subject: [PATCH 16/38] Apply formatter --- python_tests/test_api.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/python_tests/test_api.py b/python_tests/test_api.py index ebe5a0ef..cbf36e0c 100644 --- a/python_tests/test_api.py +++ b/python_tests/test_api.py @@ -1,14 +1,13 @@ from __future__ import annotations import json -import pytest import sys +from typing import Any from unittest import TestCase import optuna from optuna import get_all_study_summaries from optuna.study import StudyDirection -from optuna.trial import FrozenTrial from optuna_dashboard._app import create_app from optuna_dashboard._app import create_new_study from optuna_dashboard._note import note_str_key_prefix @@ -47,8 +46,10 @@ class APITestCase(TestCase): self.assertEqual(len(study_summaries), 2) def run_get_study_details( - self, queries: dict[str, str] | None = None, expected_status: int = 200, - ) -> tuple[int, list[FrozenTrial]]: + self, + queries: dict[str, str] | None = None, + expected_status: int = 200, + ) -> list[dict[str, Any]]: study = optuna.create_study() study_id = study._study_id study.optimize(objective, n_trials=10) From 78e1e118029c43281e7620bbeacb879c85aa8670 Mon Sep 17 00:00:00 2001 From: nabenabe0928 Date: Fri, 19 Jan 2024 07:38:52 +0100 Subject: [PATCH 17/38] Add the force update for disabled live update --- optuna_dashboard/_app.py | 3 ++- optuna_dashboard/ts/action.ts | 4 ++-- optuna_dashboard/ts/components/AppDrawer.tsx | 7 ++++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/optuna_dashboard/_app.py b/optuna_dashboard/_app.py index a0be6770..318135b0 100644 --- a/optuna_dashboard/_app.py +++ b/optuna_dashboard/_app.py @@ -192,7 +192,7 @@ def create_app( @json_api_view def get_study_detail(study_id: int) -> dict[str, Any]: # Use the following default values if not specified in request.params. - query_params = dict(after=0, limit=1000) + query_params = dict(after=0, limit=2000) for query_key in query_params: try: query_params[query_key] = int(request.params[query_key]) @@ -235,6 +235,7 @@ def create_app( plotly_graph_objects = get_plotly_graph_objects(system_attrs) skipped_trial_ids = get_skipped_trial_ids(system_attrs) skipped_trial_numbers = [t.number for t in trials if t._trial_id in skipped_trial_ids] + limit = len(trials) if limit == 0 else limit fetched_trials_partially = after + limit < len(trials) return serialize_study_detail( summary, diff --git a/optuna_dashboard/ts/action.ts b/optuna_dashboard/ts/action.ts index a54e09ea..159e22fe 100644 --- a/optuna_dashboard/ts/action.ts +++ b/optuna_dashboard/ts/action.ts @@ -235,9 +235,9 @@ export const actionCreator = () => { }) } - const updateStudyDetail = (studyId: number) => { + const updateStudyDetail = (studyId: number, forceFetchAllTrials: boolean = false) => { let nLocalFixedTrials = 0 - const nMaximumTrialsAtOnce = 2000 + const nMaximumTrialsAtOnce = forceFetchAllTrials ? 0 : 2000 if (studyId in studyDetails) { const currentTrials = studyDetails[studyId].trials const firstUpdatable = currentTrials.findIndex((trial) => diff --git a/optuna_dashboard/ts/components/AppDrawer.tsx b/optuna_dashboard/ts/components/AppDrawer.tsx index 31eeec69..0c17f338 100644 --- a/optuna_dashboard/ts/components/AppDrawer.tsx +++ b/optuna_dashboard/ts/components/AppDrawer.tsx @@ -310,7 +310,12 @@ export const AppDrawer: FC<{ { - action.saveReloadInterval(reloadInterval === -1 ? 10 : -1) + const newReloadInterval = reloadInterval === -1 ? 10 : -1 + action.saveReloadInterval(newReloadInterval) + if (newReloadInterval === -1) { + const forceFetchAllTrials = true + action.updateStudyDetail(studyId, forceFetchAllTrials) + } }} > From c10be8fcb8c49ab3f95ddc94d3bb1418cb8c620f Mon Sep 17 00:00:00 2001 From: nabenabe0928 Date: Fri, 19 Jan 2024 08:45:39 +0100 Subject: [PATCH 18/38] Apply formatter --- optuna_dashboard/ts/action.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/optuna_dashboard/ts/action.ts b/optuna_dashboard/ts/action.ts index 159e22fe..4f7cb006 100644 --- a/optuna_dashboard/ts/action.ts +++ b/optuna_dashboard/ts/action.ts @@ -235,7 +235,10 @@ export const actionCreator = () => { }) } - const updateStudyDetail = (studyId: number, forceFetchAllTrials: boolean = false) => { + const updateStudyDetail = ( + studyId: number, + forceFetchAllTrials: boolean = false + ) => { let nLocalFixedTrials = 0 const nMaximumTrialsAtOnce = forceFetchAllTrials ? 0 : 2000 if (studyId in studyDetails) { From 4828089fdff7d52a5f5b0e676442a46310fa359d Mon Sep 17 00:00:00 2001 From: Kenshin Abe Date: Fri, 26 Jan 2024 19:08:19 +0900 Subject: [PATCH 19/38] Split useBackendRender function --- optuna_dashboard/ts/components/GraphContour.tsx | 17 +++-------------- optuna_dashboard/ts/state.ts | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphContour.tsx b/optuna_dashboard/ts/components/GraphContour.tsx index 2c660a89..7f59e718 100644 --- a/optuna_dashboard/ts/components/GraphContour.tsx +++ b/optuna_dashboard/ts/components/GraphContour.tsx @@ -15,27 +15,16 @@ import blue from "@mui/material/colors/blue" import { plotlyDarkTemplate } from "./PlotlyDarkMode" import { useMergedUnionSearchSpace } from "../searchSpace" import { getAxisInfo } from "../graphUtil" -import { useQuery } from "../urlQuery" import { getPlotAPI, PlotType } from "../apiClient" -import { useRecoilValue } from "recoil" -import { plotlypyIsAvailableState } from "../state" +import { useBackendRender } from "../state" const plotDomId = "graph-contour" export const Contour: FC<{ study: StudyDetail | null }> = ({ study = null }) => { - const query = useQuery() - const plotlypyIsAvailable = useRecoilValue(plotlypyIsAvailableState) - if (query.get("plotlypy_rendering") === "true") { - if (plotlypyIsAvailable) { - return - } else { - console.warn( - "Use frontend rendering because plotlypy is specified but not available." - ) - return - } + if (useBackendRender()) { + return } else { return } diff --git a/optuna_dashboard/ts/state.ts b/optuna_dashboard/ts/state.ts index 49307401..20f75c2d 100644 --- a/optuna_dashboard/ts/state.ts +++ b/optuna_dashboard/ts/state.ts @@ -1,4 +1,5 @@ import { atom, useRecoilValue } from "recoil" +import { useQuery } from "./urlQuery" export const studySummariesState = atom({ key: "studySummaries", @@ -104,3 +105,18 @@ export const useArtifacts = (studyId: number, trialId: number): Artifact[] => { } return trial.artifacts } + +export const useBackendRender = (): boolean => { + const query = useQuery() + const plotlypyIsAvailable = useRecoilValue(plotlypyIsAvailableState) + + if (query.get("plotlypy_rendering") === "true") { + if (plotlypyIsAvailable) { + return true + } + console.warn( + "Use frontend rendering because plotlypy is specified but not available." + ) + } + return false +} From 94ce9f9fa162ddf19653377e68794f86d682a2c9 Mon Sep 17 00:00:00 2001 From: Kenshin Abe Date: Fri, 26 Jan 2024 19:12:24 +0900 Subject: [PATCH 20/38] Implement API --- optuna_dashboard/_app.py | 8 ++++++++ optuna_dashboard/ts/apiClient.ts | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/optuna_dashboard/_app.py b/optuna_dashboard/_app.py index 1c9c0119..5057353d 100644 --- a/optuna_dashboard/_app.py +++ b/optuna_dashboard/_app.py @@ -271,6 +271,14 @@ def create_app( ) if plot_type == "contour": fig = optuna.visualization.plot_contour(study) + elif plot_type == "slice": + fig = optuna.visualization.plot_slice(study) + elif plot_type == "parallel_coordinate": + fig = optuna.visualization.plot_parallel_coordinate(study) + elif plot_type == "rank": + fig = optuna.visualization.plot_rank(study) + elif plot_type == "edf": + fig = optuna.visualization.plot_edf(study) else: response.status = 404 # Not found return {"reason": f"plot_type={plot_type} is not supported."} diff --git a/optuna_dashboard/ts/apiClient.ts b/optuna_dashboard/ts/apiClient.ts index 3798f602..46fe3d0e 100644 --- a/optuna_dashboard/ts/apiClient.ts +++ b/optuna_dashboard/ts/apiClient.ts @@ -448,6 +448,10 @@ type PlotResponse = { } export enum PlotType { Contour = "contour", + Slice = "slice", + ParallelCoordinate = "parallel_coordinate", + Rank = "rank", + EDF = "edf", } export const getPlotAPI = ( studyId: number, From 78a7b9dbaab456499d1b41852f907c5b8ee62a35 Mon Sep 17 00:00:00 2001 From: Kenshin Abe Date: Fri, 26 Jan 2024 19:13:06 +0900 Subject: [PATCH 21/38] Implement GraphSliceBackend --- optuna_dashboard/ts/components/GraphSlice.tsx | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/optuna_dashboard/ts/components/GraphSlice.tsx b/optuna_dashboard/ts/components/GraphSlice.tsx index 2a807cb7..c668423c 100644 --- a/optuna_dashboard/ts/components/GraphSlice.tsx +++ b/optuna_dashboard/ts/components/GraphSlice.tsx @@ -20,6 +20,8 @@ import { useParamTargets, } from "../trialFilter" import { useMergedUnionSearchSpace } from "../searchSpace" +import { getPlotAPI, PlotType } from "../apiClient" +import { useBackendRender } from "../state" const plotDomId = "graph-slice" @@ -32,6 +34,35 @@ const isLogScale = (s: SearchSpaceItem): boolean => { export const GraphSlice: FC<{ study: StudyDetail | null +}> = ({ study = null }) => { + if (useBackendRender()) { + return + } else { + return + } +} + +const GraphSliceBackend: FC<{ + study: StudyDetail | null +}> = ({ study = null }) => { + const studyId = study?.id + useEffect(() => { + if (studyId === undefined) { + return + } + getPlotAPI(studyId, PlotType.Slice) + .then(({ data, layout }) => { + plotly.react(plotDomId, data, layout) + }) + .catch((err) => { + console.error(err) + }) + }, [studyId]) + return +} + +const GraphSliceFrontend: FC<{ + study: StudyDetail | null }> = ({ study = null }) => { const theme = useTheme() From 55cca4a76e032da5c51773c69d75748216dd49e1 Mon Sep 17 00:00:00 2001 From: Kenshin Abe Date: Fri, 26 Jan 2024 19:17:24 +0900 Subject: [PATCH 22/38] Implement GraphParallelCoordinateBackend --- .../ts/components/GraphParallelCoordinate.tsx | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/optuna_dashboard/ts/components/GraphParallelCoordinate.tsx b/optuna_dashboard/ts/components/GraphParallelCoordinate.tsx index b991ef94..3a227237 100644 --- a/optuna_dashboard/ts/components/GraphParallelCoordinate.tsx +++ b/optuna_dashboard/ts/components/GraphParallelCoordinate.tsx @@ -17,6 +17,8 @@ import { useParamTargets, } from "../trialFilter" import { useMergedUnionSearchSpace } from "../searchSpace" +import { getPlotAPI, PlotType } from "../apiClient" +import { useBackendRender } from "../state" const plotDomId = "graph-parallel-coordinate" @@ -86,6 +88,35 @@ const useTargets = ( export const GraphParallelCoordinate: FC<{ study: StudyDetail | null +}> = ({ study = null }) => { + if (useBackendRender()) { + return + } else { + return + } +} + +const GraphParallelCoordinateBackend: FC<{ + study: StudyDetail | null +}> = ({ study = null }) => { + const studyId = study?.id + useEffect(() => { + if (studyId === undefined) { + return + } + getPlotAPI(studyId, PlotType.ParallelCoordinate) + .then(({ data, layout }) => { + plotly.react(plotDomId, data, layout) + }) + .catch((err) => { + console.error(err) + }) + }, [studyId]) + return +} + +const GraphParallelCoordinateFrontend: FC<{ + study: StudyDetail | null }> = ({ study = null }) => { const theme = useTheme() const [targets, searchSpace, renderCheckBoxes] = useTargets(study) From 27cdde3a1b82dde94d2f89fe2013daac70eb0cd4 Mon Sep 17 00:00:00 2001 From: Kenshin Abe Date: Fri, 26 Jan 2024 19:19:35 +0900 Subject: [PATCH 23/38] Implement GraphRankBackend --- optuna_dashboard/ts/components/GraphRank.tsx | 31 ++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/optuna_dashboard/ts/components/GraphRank.tsx b/optuna_dashboard/ts/components/GraphRank.tsx index 6daaf10a..3ee4f9df 100644 --- a/optuna_dashboard/ts/components/GraphRank.tsx +++ b/optuna_dashboard/ts/components/GraphRank.tsx @@ -14,6 +14,8 @@ import { import { plotlyDarkTemplate } from "./PlotlyDarkMode" import { getAxisInfo, makeHovertext } from "../graphUtil" import { useMergedUnionSearchSpace } from "../searchSpace" +import { getPlotAPI, PlotType } from "../apiClient" +import { useBackendRender } from "../state" const plotDomId = "graph-rank" @@ -31,6 +33,35 @@ interface RankPlotInfo { export const GraphRank: FC<{ study: StudyDetail | null +}> = ({ study = null }) => { + if (useBackendRender()) { + return + } else { + return + } +} + +const GraphRankBackend: FC<{ + study: StudyDetail | null +}> = ({ study = null }) => { + const studyId = study?.id + useEffect(() => { + if (studyId === undefined) { + return + } + getPlotAPI(studyId, PlotType.Rank) + .then(({ data, layout }) => { + plotly.react(plotDomId, data, layout) + }) + .catch((err) => { + console.error(err) + }) + }, [studyId]) + return +} + +const GraphRankFrontend: FC<{ + study: StudyDetail | null }> = ({ study = null }) => { const theme = useTheme() const [objectiveId, setobjectiveId] = useState(0) From 713c8f3443ce4d3f687d2c4f3cc0a42f304a9534 Mon Sep 17 00:00:00 2001 From: keisuke-umezawa Date: Sat, 27 Jan 2024 14:10:16 +0900 Subject: [PATCH 24/38] Aligh button design --- .../ts/components/StudyDetail.tsx | 26 ----------------- optuna_dashboard/ts/components/TrialTable.tsx | 29 ++++++++++++++----- 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/optuna_dashboard/ts/components/StudyDetail.tsx b/optuna_dashboard/ts/components/StudyDetail.tsx index 2f56ec8b..d928daa4 100644 --- a/optuna_dashboard/ts/components/StudyDetail.tsx +++ b/optuna_dashboard/ts/components/StudyDetail.tsx @@ -150,32 +150,6 @@ export const StudyDetail: FC<{ } else if (page === "trialTable") { content = ( - - - - - - Download CSV File - - - - diff --git a/optuna_dashboard/ts/components/TrialTable.tsx b/optuna_dashboard/ts/components/TrialTable.tsx index efc79626..98a0b176 100644 --- a/optuna_dashboard/ts/components/TrialTable.tsx +++ b/optuna_dashboard/ts/components/TrialTable.tsx @@ -1,6 +1,7 @@ import React, { FC } from "react" -import { IconButton } from "@mui/material" +import { IconButton, Button, useTheme } from "@mui/material" import LinkIcon from "@mui/icons-material/Link" +import DownloadIcon from "@mui/icons-material/Download" import { DataGridColumn, DataGrid } from "./DataGrid" import { Link } from "react-router-dom" @@ -9,6 +10,7 @@ export const TrialTable: FC<{ studyDetail: StudyDetail | null initialRowsPerPage?: number }> = ({ studyDetail, initialRowsPerPage }) => { + const theme = useTheme() const trials: Trial[] = studyDetail !== null ? studyDetail.trials : [] const objectiveNames: string[] = studyDetail?.objective_names || [] @@ -190,12 +192,23 @@ export const TrialTable: FC<{ }) return ( - - columns={columns} - rows={trials} - keyField={"trial_id"} - dense={true} - initialRowsPerPage={initialRowsPerPage} - /> + <> + + columns={columns} + rows={trials} + keyField={"trial_id"} + dense={true} + initialRowsPerPage={initialRowsPerPage} + /> + + ) } From 33d913d6ea1ae88aa0658b482d0e2a168554873c Mon Sep 17 00:00:00 2001 From: keisuke-umezawa Date: Sat, 27 Jan 2024 14:31:43 +0900 Subject: [PATCH 25/38] Fix lint --- optuna_dashboard/ts/components/StudyDetail.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/optuna_dashboard/ts/components/StudyDetail.tsx b/optuna_dashboard/ts/components/StudyDetail.tsx index d928daa4..92856a6e 100644 --- a/optuna_dashboard/ts/components/StudyDetail.tsx +++ b/optuna_dashboard/ts/components/StudyDetail.tsx @@ -12,7 +12,6 @@ import { import Grid2 from "@mui/material/Unstable_Grid2" import ChevronRightIcon from "@mui/icons-material/ChevronRight" import HomeIcon from "@mui/icons-material/Home" -import DownloadIcon from "@mui/icons-material/Download" import { StudyNote } from "./Note" import { actionCreator } from "../action" From b2756fd33994289eacb2ad24224a300f1fdcd6ac Mon Sep 17 00:00:00 2001 From: Kenshin Abe Date: Fri, 2 Feb 2024 18:07:13 +0900 Subject: [PATCH 26/38] Prevent plot from being wider than screen width --- optuna_dashboard/_app.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/optuna_dashboard/_app.py b/optuna_dashboard/_app.py index 5057353d..0ba94b1a 100644 --- a/optuna_dashboard/_app.py +++ b/optuna_dashboard/_app.py @@ -273,6 +273,10 @@ def create_app( fig = optuna.visualization.plot_contour(study) elif plot_type == "slice": fig = optuna.visualization.plot_slice(study) + # Note: Optuna's implementation forces a minimum width. + # We override it to prevent the figure from going beyond the screen width. + # https://github.com/optuna/optuna/blob/2abd0ae81eaf3683ce1dd580429904c8a705300d/optuna/visualization/_slice.py#L237-L239 + fig.update_layout(width=None) elif plot_type == "parallel_coordinate": fig = optuna.visualization.plot_parallel_coordinate(study) elif plot_type == "rank": From 91f1754c429a38b9cf9fc565e8ee0dff0148309d Mon Sep 17 00:00:00 2001 From: porink0424 Date: Fri, 2 Feb 2024 18:38:00 +0900 Subject: [PATCH 27/38] Fix some tiny format problems --- optuna_dashboard/ts/components/GraphHistory.tsx | 4 ++-- optuna_dashboard/ts/components/GraphParetoFront.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphHistory.tsx b/optuna_dashboard/ts/components/GraphHistory.tsx index a2b58c14..0afcb555 100644 --- a/optuna_dashboard/ts/components/GraphHistory.tsx +++ b/optuna_dashboard/ts/components/GraphHistory.tsx @@ -72,9 +72,9 @@ export const GraphHistory: FC<{ markerSize ) const element = document.getElementById(plotDomId) - if (element != null && studies.length >= 1) { + if (element !== null && studies.length >= 1) { // @ts-ignore - element.on("plotly_click", function (data) { + element.on("plotly_click", (data) => { if (data.points[0].data.mode !== "lines") { let studyId = 1 if (data.points[0].data.name.includes("Infeasible Trial of")) { diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index d8911fd2..f2b11145 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -40,7 +40,7 @@ export const GraphParetoFront: FC<{ const element = document.getElementById(plotDomId) if (element != null) { // @ts-ignore - element.on("plotly_click", function (data) { + element.on("plotly_click", (data) => { const plotTextInfo = JSON.parse( data.points[0].text.replace(/
/g, "") ) From 35baab0117514c0a1ce499f3addcdb8c2968af98 Mon Sep 17 00:00:00 2001 From: Kenshin Abe Date: Fri, 2 Feb 2024 18:59:50 +0900 Subject: [PATCH 28/38] Fetch plot API when num_trials is updated --- optuna_dashboard/ts/components/GraphContour.tsx | 4 +++- optuna_dashboard/ts/components/GraphParallelCoordinate.tsx | 4 +++- optuna_dashboard/ts/components/GraphRank.tsx | 4 +++- optuna_dashboard/ts/components/GraphSlice.tsx | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/optuna_dashboard/ts/components/GraphContour.tsx b/optuna_dashboard/ts/components/GraphContour.tsx index 7f59e718..c0c296de 100644 --- a/optuna_dashboard/ts/components/GraphContour.tsx +++ b/optuna_dashboard/ts/components/GraphContour.tsx @@ -34,6 +34,8 @@ const ContourBackend: FC<{ study: StudyDetail | null }> = ({ study = null }) => { const studyId = study?.id + const numCompletedTrials = + study?.trials.filter((t) => t.state === "Complete").length || 0 useEffect(() => { if (studyId === undefined) { return @@ -45,7 +47,7 @@ const ContourBackend: FC<{ .catch((err) => { console.error(err) }) - }, [studyId]) + }, [studyId, numCompletedTrials]) return } diff --git a/optuna_dashboard/ts/components/GraphParallelCoordinate.tsx b/optuna_dashboard/ts/components/GraphParallelCoordinate.tsx index 3a227237..22d4852a 100644 --- a/optuna_dashboard/ts/components/GraphParallelCoordinate.tsx +++ b/optuna_dashboard/ts/components/GraphParallelCoordinate.tsx @@ -100,6 +100,8 @@ const GraphParallelCoordinateBackend: FC<{ study: StudyDetail | null }> = ({ study = null }) => { const studyId = study?.id + const numCompletedTrials = + study?.trials.filter((t) => t.state === "Complete").length || 0 useEffect(() => { if (studyId === undefined) { return @@ -111,7 +113,7 @@ const GraphParallelCoordinateBackend: FC<{ .catch((err) => { console.error(err) }) - }, [studyId]) + }, [studyId, numCompletedTrials]) return } diff --git a/optuna_dashboard/ts/components/GraphRank.tsx b/optuna_dashboard/ts/components/GraphRank.tsx index 3ee4f9df..ab25afeb 100644 --- a/optuna_dashboard/ts/components/GraphRank.tsx +++ b/optuna_dashboard/ts/components/GraphRank.tsx @@ -45,6 +45,8 @@ const GraphRankBackend: FC<{ study: StudyDetail | null }> = ({ study = null }) => { const studyId = study?.id + const numCompletedTrials = + study?.trials.filter((t) => t.state === "Complete").length || 0 useEffect(() => { if (studyId === undefined) { return @@ -56,7 +58,7 @@ const GraphRankBackend: FC<{ .catch((err) => { console.error(err) }) - }, [studyId]) + }, [studyId, numCompletedTrials]) return } diff --git a/optuna_dashboard/ts/components/GraphSlice.tsx b/optuna_dashboard/ts/components/GraphSlice.tsx index c668423c..6abaca50 100644 --- a/optuna_dashboard/ts/components/GraphSlice.tsx +++ b/optuna_dashboard/ts/components/GraphSlice.tsx @@ -46,6 +46,8 @@ const GraphSliceBackend: FC<{ study: StudyDetail | null }> = ({ study = null }) => { const studyId = study?.id + const numCompletedTrials = + study?.trials.filter((t) => t.state === "Complete").length || 0 useEffect(() => { if (studyId === undefined) { return @@ -57,7 +59,7 @@ const GraphSliceBackend: FC<{ .catch((err) => { console.error(err) }) - }, [studyId]) + }, [studyId, numCompletedTrials]) return } From 15ca335b07442bc772cbdcc02cb8a989832bd095 Mon Sep 17 00:00:00 2001 From: Kenshin Abe Date: Fri, 2 Feb 2024 19:25:07 +0900 Subject: [PATCH 29/38] Implement compare-studies API --- optuna_dashboard/_app.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/optuna_dashboard/_app.py b/optuna_dashboard/_app.py index dfa7338c..ac0e1cf0 100644 --- a/optuna_dashboard/_app.py +++ b/optuna_dashboard/_app.py @@ -288,6 +288,21 @@ def create_app( return {"reason": f"plot_type={plot_type} is not supported."} return fig.to_json() + @app.get("/api/compare-studies/plot/") + @json_api_view + def get_compare_studies_plot(plot_type: str) -> dict[str, Any]: + study_ids = map(int, request.query.getall("study_ids[]")) + studies = [ + optuna.load_study(study_name=storage.get_study_name_from_id(study_id), storage=storage) + for study_id in study_ids + ] + if plot_type == "edf": + fig = optuna.visualization.plot_edf(studies) + else: + response.status = 404 # Not found + return {"reason": f"plot_type={plot_type} is not supported."} + return fig.to_json() + @app.put("/api/studies//note") @json_api_view def save_study_note(study_id: int) -> dict[str, Any]: From b2a9b3bb50429268e361f0750383dee6f3ea8c24 Mon Sep 17 00:00:00 2001 From: Kenshin Abe Date: Fri, 2 Feb 2024 19:28:00 +0900 Subject: [PATCH 30/38] Implement GraphEdfBackend --- optuna_dashboard/ts/apiClient.ts | 14 +++++++++ optuna_dashboard/ts/components/GraphEdf.tsx | 33 +++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/optuna_dashboard/ts/apiClient.ts b/optuna_dashboard/ts/apiClient.ts index 46fe3d0e..5339ff21 100644 --- a/optuna_dashboard/ts/apiClient.ts +++ b/optuna_dashboard/ts/apiClient.ts @@ -461,3 +461,17 @@ export const getPlotAPI = ( .get(`/api/studies/${studyId}/plot/${plotType}`) .then((res) => res.data) } + +export enum CompareStudiesPlotType { + EDF = "edf", +} +export const getCompareStudiesPlotAPI = ( + studyIds: number[], + plotType: CompareStudiesPlotType, +): Promise => { + return axiosInstance + .get(`/api/compare-studies/plot/${plotType}`, { + params: { study_ids: studyIds }, + }) + .then((res) => res.data) +} diff --git a/optuna_dashboard/ts/components/GraphEdf.tsx b/optuna_dashboard/ts/components/GraphEdf.tsx index ca85ee54..6bb65bdc 100644 --- a/optuna_dashboard/ts/components/GraphEdf.tsx +++ b/optuna_dashboard/ts/components/GraphEdf.tsx @@ -3,6 +3,8 @@ import React, { FC, useEffect, useMemo } from "react" import { Typography, useTheme, Box } from "@mui/material" import { plotlyDarkTemplate } from "./PlotlyDarkMode" import { Target, useFilteredTrialsFromStudies } from "../trialFilter" +import { getCompareStudiesPlotAPI, CompareStudiesPlotType } from "../apiClient" +import { useBackendRender } from "../state" const getPlotDomId = (objectiveId: number) => `graph-edf-${objectiveId}` @@ -14,6 +16,37 @@ interface EdfPlotInfo { export const GraphEdf: FC<{ studies: StudyDetail[] objectiveId: number +}> = ({ studies, objectiveId }) => { + if (useBackendRender()) { + return + } else { + return + } +} + +const GraphEdfBackend: FC<{ + studies: StudyDetail[] +}> = ({ studies }) => { + const studyIds = studies.map((s) => s.id) + const domId = getPlotDomId(-1) + useEffect(() => { + if (studyIds.length === 0) { + return + } + getCompareStudiesPlotAPI(studyIds, CompareStudiesPlotType.EDF) + .then(({ data, layout }) => { + plotly.react(domId, data, layout) + }) + .catch((err) => { + console.error(err) + }) + }, [studyIds]) + return +} + +const GraphEdfFrontend: FC<{ + studies: StudyDetail[] + objectiveId: number }> = ({ studies, objectiveId }) => { const theme = useTheme() const domId = getPlotDomId(objectiveId) From fe538ac2fd89a676a92dc33b1f1bbabbe804de1e Mon Sep 17 00:00:00 2001 From: Kenshin Abe Date: Fri, 2 Feb 2024 19:32:53 +0900 Subject: [PATCH 31/38] Use numCompletedTrials --- optuna_dashboard/ts/components/GraphEdf.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/optuna_dashboard/ts/components/GraphEdf.tsx b/optuna_dashboard/ts/components/GraphEdf.tsx index 6bb65bdc..dffa7274 100644 --- a/optuna_dashboard/ts/components/GraphEdf.tsx +++ b/optuna_dashboard/ts/components/GraphEdf.tsx @@ -29,6 +29,11 @@ const GraphEdfBackend: FC<{ }> = ({ studies }) => { const studyIds = studies.map((s) => s.id) const domId = getPlotDomId(-1) + const numCompletedTrials = studies.reduce( + (acc, study) => + acc + study?.trials.filter((t) => t.state === "Complete").length, + 0 + ) useEffect(() => { if (studyIds.length === 0) { return @@ -40,7 +45,7 @@ const GraphEdfBackend: FC<{ .catch((err) => { console.error(err) }) - }, [studyIds]) + }, [studyIds, numCompletedTrials]) return } From b5c1260bbbd99bbc1ba222052bc695d9209cbcb1 Mon Sep 17 00:00:00 2001 From: Kenshin Abe Date: Fri, 2 Feb 2024 19:32:57 +0900 Subject: [PATCH 32/38] Format --- optuna_dashboard/ts/apiClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optuna_dashboard/ts/apiClient.ts b/optuna_dashboard/ts/apiClient.ts index 5339ff21..14566a07 100644 --- a/optuna_dashboard/ts/apiClient.ts +++ b/optuna_dashboard/ts/apiClient.ts @@ -467,7 +467,7 @@ export enum CompareStudiesPlotType { } export const getCompareStudiesPlotAPI = ( studyIds: number[], - plotType: CompareStudiesPlotType, + plotType: CompareStudiesPlotType ): Promise => { return axiosInstance .get(`/api/compare-studies/plot/${plotType}`, { From 08fc115638e4b508fbd78074d64e2624ec70aeff Mon Sep 17 00:00:00 2001 From: porink0424 Date: Tue, 6 Feb 2024 10:18:10 +0900 Subject: [PATCH 33/38] Migrate to biome.js from prettier --- .prettierignore | 2 - .prettierrc | 4 - biome.json | 28 +++ .../Artifact/DeleteArtifactDialog.tsx | 4 +- .../Artifact/ThreejsArtifactViewer.tsx | 2 +- .../Artifact/WaveSurferArtifactViewer.tsx | 59 +++-- optuna_dashboard/ts/components/DataGrid.tsx | 8 +- .../ts/components/DeleteStudyDialog.tsx | 2 +- .../ts/components/GraphHistory.tsx | 4 +- .../ts/components/GraphIntermediateValues.tsx | 4 +- .../ts/components/GraphParetoFront.tsx | 12 +- optuna_dashboard/ts/components/GraphRank.tsx | 4 +- .../ts/components/TrialFormWidgets.tsx | 4 +- optuna_dashboard/ts/graphUtil.ts | 4 +- package-lock.json | 228 ++++++++++++++++++ package.json | 5 +- standalone_app/src/components/DataGrid.tsx | 4 +- standalone_app/src/components/PlotHistory.tsx | 4 +- standalone_app/src/sqlite3.ts | 24 +- 19 files changed, 328 insertions(+), 78 deletions(-) delete mode 100644 .prettierignore delete mode 100644 .prettierrc create mode 100644 biome.json diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index e7faf7a6..00000000 --- a/.prettierignore +++ /dev/null @@ -1,2 +0,0 @@ -optuna_dashboard/ts/components/PlotlyDarkMode.ts -standalone_app/src/PlotlyDarkMode.ts diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 24ae9a99..00000000 --- a/.prettierrc +++ /dev/null @@ -1,4 +0,0 @@ -trailingComma: "es5" -tabWidth: 2 -semi: false -singleQuote: false diff --git a/biome.json b/biome.json new file mode 100644 index 00000000..740e9600 --- /dev/null +++ b/biome.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.5.3/schema.json", + "files": { + "include": [ + "optuna_dashboard/ts/**/*.ts", + "optuna_dashboard/ts/**/*.tsx", + "typescript_tests/**/*.ts", + "typescript_tests/**/*.tsx", + "standalone_app/src/**/*.ts", + "standalone_app/src/**/*.tsx", + "vscode/src/**/*.ts", + "vscode/src/**/*.tsx" + ], + "ignore": [ + "optuna_dashboard/ts/components/PlotlyDarkMode.ts", + "standalone_app/src/PlotlyDarkMode.ts" + ] + }, + "javascript": { + "formatter": { + "trailingComma": "es5", + "indentWidth": 2, + "indentStyle": "space", + "semicolons": "asNeeded", + "quoteStyle": "double" + } + } +} diff --git a/optuna_dashboard/ts/components/Artifact/DeleteArtifactDialog.tsx b/optuna_dashboard/ts/components/Artifact/DeleteArtifactDialog.tsx index 2055ea4c..4c2f16d1 100644 --- a/optuna_dashboard/ts/components/Artifact/DeleteArtifactDialog.tsx +++ b/optuna_dashboard/ts/components/Artifact/DeleteArtifactDialog.tsx @@ -11,7 +11,7 @@ import { actionCreator } from "../../action" export const useDeleteTrialArtifactDialog = (): [ (studyId: number, trialId: number, artifact: Artifact) => void, - () => ReactNode + () => ReactNode, ] => { const action = actionCreator() @@ -58,7 +58,7 @@ export const useDeleteTrialArtifactDialog = (): [ export const useDeleteStudyArtifactDialog = (): [ (studyId: number, artifact: Artifact) => void, - () => ReactNode + () => ReactNode, ] => { const action = actionCreator() diff --git a/optuna_dashboard/ts/components/Artifact/ThreejsArtifactViewer.tsx b/optuna_dashboard/ts/components/Artifact/ThreejsArtifactViewer.tsx index 8e574680..7787e8a4 100644 --- a/optuna_dashboard/ts/components/Artifact/ThreejsArtifactViewer.tsx +++ b/optuna_dashboard/ts/components/Artifact/ThreejsArtifactViewer.tsx @@ -124,7 +124,7 @@ export const ThreejsArtifactViewer: React.FC = ( export const useThreejsArtifactModal = (): [ (path: string, artifact: Artifact) => void, - () => ReactNode + () => ReactNode, ] => { const [open, setOpen] = useState(false) const [target, setTarget] = useState<[string, Artifact | null]>(["", null]) diff --git a/optuna_dashboard/ts/components/Artifact/WaveSurferArtifactViewer.tsx b/optuna_dashboard/ts/components/Artifact/WaveSurferArtifactViewer.tsx index 74177602..96713e69 100644 --- a/optuna_dashboard/ts/components/Artifact/WaveSurferArtifactViewer.tsx +++ b/optuna_dashboard/ts/components/Artifact/WaveSurferArtifactViewer.tsx @@ -34,39 +34,38 @@ const useWavesurfer = ( } // Create a React component of wavesurfer. -export const WaveSurferArtifactViewer: React.FC< - WaveSurferArtifactViewerProps -> = (props) => { - const containerRef = useRef(null!) - const [isPlaying, setIsPlaying] = useState(false) - const wavesurfer = useWavesurfer(containerRef, props) +export const WaveSurferArtifactViewer: React.FC = + (props) => { + const containerRef = useRef(null!) + const [isPlaying, setIsPlaying] = useState(false) + const wavesurfer = useWavesurfer(containerRef, props) - const onPlayClick = useCallback(() => { - if (!wavesurfer) return - wavesurfer.isPlaying() ? wavesurfer.pause() : wavesurfer.play() - }, [wavesurfer]) + const onPlayClick = useCallback(() => { + if (!wavesurfer) return + wavesurfer.isPlaying() ? wavesurfer.pause() : wavesurfer.play() + }, [wavesurfer]) - useEffect(() => { - if (!wavesurfer) return + useEffect(() => { + if (!wavesurfer) return - setIsPlaying(false) + setIsPlaying(false) - const subscriptions = [ - wavesurfer.on("play", () => setIsPlaying(true)), - wavesurfer.on("pause", () => setIsPlaying(false)), - ] + const subscriptions = [ + wavesurfer.on("play", () => setIsPlaying(true)), + wavesurfer.on("pause", () => setIsPlaying(false)), + ] - return () => { - subscriptions.forEach((unsub) => unsub()) - } - }, [wavesurfer]) + return () => { + subscriptions.forEach((unsub) => unsub()) + } + }, [wavesurfer]) - return ( - -
- - - ) -} + return ( + +
+ + + ) + } diff --git a/optuna_dashboard/ts/components/DataGrid.tsx b/optuna_dashboard/ts/components/DataGrid.tsx index 22693a5b..2aaba509 100644 --- a/optuna_dashboard/ts/components/DataGrid.tsx +++ b/optuna_dashboard/ts/components/DataGrid.tsx @@ -71,8 +71,8 @@ function DataGrid(props: { initialRowsPerPage = initialRowsPerPage // use first element as default ? initialRowsPerPage : isNumber(rowsPerPageOption[0]) - ? rowsPerPageOption[0] - : rowsPerPageOption[0].value + ? rowsPerPageOption[0] + : rowsPerPageOption[0].value const [rowsPerPage, setRowsPerPage] = React.useState(initialRowsPerPage) const handleChangePage = (event: unknown, newPage: number) => { @@ -321,8 +321,8 @@ function DataGridHeaderColumn(props: { filter === null ? filterChoices.filter((v) => v !== choice) // By default, every choice is ticked, so the chosen option will be unticked. : filter.values.some((v) => v === choice) - ? filter.values.filter((v) => v !== choice) - : [...filter.values, choice] + ? filter.values.filter((v) => v !== choice) + : [...filter.values, choice] onFilterChange(newTickedValues) }} > diff --git a/optuna_dashboard/ts/components/DeleteStudyDialog.tsx b/optuna_dashboard/ts/components/DeleteStudyDialog.tsx index c7d7a135..73940b2a 100644 --- a/optuna_dashboard/ts/components/DeleteStudyDialog.tsx +++ b/optuna_dashboard/ts/components/DeleteStudyDialog.tsx @@ -11,7 +11,7 @@ import { actionCreator } from "../action" export const useDeleteStudyDialog = (): [ (studyId: number) => void, - () => ReactNode + () => ReactNode, ] => { const action = actionCreator() diff --git a/optuna_dashboard/ts/components/GraphHistory.tsx b/optuna_dashboard/ts/components/GraphHistory.tsx index a2b58c14..57d5c4fd 100644 --- a/optuna_dashboard/ts/components/GraphHistory.tsx +++ b/optuna_dashboard/ts/components/GraphHistory.tsx @@ -251,8 +251,8 @@ const plotHistory = ( return xAxis === "number" ? trial.number : xAxis === "datetime_start" - ? trial.datetime_start ?? new Date() - : trial.datetime_complete ?? new Date() + ? trial.datetime_start ?? new Date() + : trial.datetime_complete ?? new Date() } const plotData: Partial[] = [] diff --git a/optuna_dashboard/ts/components/GraphIntermediateValues.tsx b/optuna_dashboard/ts/components/GraphIntermediateValues.tsx index a06832d9..d0a3c075 100644 --- a/optuna_dashboard/ts/components/GraphIntermediateValues.tsx +++ b/optuna_dashboard/ts/components/GraphIntermediateValues.tsx @@ -95,8 +95,8 @@ const plotIntermediateValue = ( trial.state === "Running" ? "(running)" : !isFeasible - ? "(infeasible)" - : "" + ? "(infeasible)" + : "" }`, ...(!isFeasible && { line: { color: "#CCCCCC" } }), } diff --git a/optuna_dashboard/ts/components/GraphParetoFront.tsx b/optuna_dashboard/ts/components/GraphParetoFront.tsx index d8911fd2..e427353d 100644 --- a/optuna_dashboard/ts/components/GraphParetoFront.tsx +++ b/optuna_dashboard/ts/components/GraphParetoFront.tsx @@ -207,12 +207,12 @@ const getIsDominated2D = (normalizedValues: number[][]) => { a[0] > b[0] ? 1 : a[0] < b[0] - ? -1 - : a[1] > b[1] - ? 1 - : a[1] < b[1] - ? -1 - : 0 + ? -1 + : a[1] > b[1] + ? 1 + : a[1] < b[1] + ? -1 + : 0 ) let maxValueSeen0 = sorted[0][0] let minValueSeen1 = sorted[0][1] diff --git a/optuna_dashboard/ts/components/GraphRank.tsx b/optuna_dashboard/ts/components/GraphRank.tsx index 3ee4f9df..a7e992b9 100644 --- a/optuna_dashboard/ts/components/GraphRank.tsx +++ b/optuna_dashboard/ts/components/GraphRank.tsx @@ -188,8 +188,8 @@ const getRankPlotInfo = ( return typeof value === "number" ? value : value.includes("-") - ? -Infinity - : Infinity + ? -Infinity + : Infinity } filteredTrials.forEach((trial, i) => { const xValue = xAxis.values[i] diff --git a/optuna_dashboard/ts/components/TrialFormWidgets.tsx b/optuna_dashboard/ts/components/TrialFormWidgets.tsx index f727ac80..36bea2a7 100644 --- a/optuna_dashboard/ts/components/TrialFormWidgets.tsx +++ b/optuna_dashboard/ts/components/TrialFormWidgets.tsx @@ -42,8 +42,8 @@ export const TrialFormWidgets: FC<{ formWidgets.output_type === "user_attr" ? "Set User Attributes Form" : directions.length > 1 - ? "Set Objective Values Form" - : "Set Objective Value Form" + ? "Set Objective Values Form" + : "Set Objective Value Form" const widgetNames = formWidgets.widgets.map((widget, i) => { if (formWidgets.output_type === "objective") { if (objectiveNames.at(i) !== undefined) { diff --git a/optuna_dashboard/ts/graphUtil.ts b/optuna_dashboard/ts/graphUtil.ts index 35a9002b..2bed664e 100644 --- a/optuna_dashboard/ts/graphUtil.ts +++ b/optuna_dashboard/ts/graphUtil.ts @@ -47,8 +47,8 @@ const getAxisInfoForCategoricalParams = ( a.toLowerCase() < b.toLowerCase() ? -1 : a.toLowerCase() > b.toLowerCase() - ? 1 - : 0 + ? 1 + : 0 ) return { name: paramName, diff --git a/package-lock.json b/package-lock.json index 1b432956..520e7f5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,7 @@ "devDependencies": { "@babel/core": "^7.23.9", "@babel/preset-env": "^7.23.9", + "@biomejs/biome": "1.5.3", "@testing-library/react": "^14.1.2", "@types/jest": "^29.5.11", "@types/plotly.js": "^2.12.32", @@ -1818,6 +1819,161 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@biomejs/biome": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.5.3.tgz", + "integrity": "sha512-yvZCa/g3akwTaAQ7PCwPWDCkZs3Qa5ONg/fgOUT9e6wAWsPftCjLQFPXBeGxPK30yZSSpgEmRCfpGTmVbUjGgg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.5.3", + "@biomejs/cli-darwin-x64": "1.5.3", + "@biomejs/cli-linux-arm64": "1.5.3", + "@biomejs/cli-linux-arm64-musl": "1.5.3", + "@biomejs/cli-linux-x64": "1.5.3", + "@biomejs/cli-linux-x64-musl": "1.5.3", + "@biomejs/cli-win32-arm64": "1.5.3", + "@biomejs/cli-win32-x64": "1.5.3" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.5.3.tgz", + "integrity": "sha512-ImU7mh1HghEDyqNmxEZBoMPr8SxekkZuYcs+gynKlNW+TALQs7swkERiBLkG9NR0K1B3/2uVzlvYowXrmlW8hw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.5.3.tgz", + "integrity": "sha512-vCdASqYnlpq/swErH7FD6nrFz0czFtK4k/iLgj0/+VmZVjineFPgevOb+Sr9vz0tk0GfdQO60bSpI74zU8M9Dw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.5.3.tgz", + "integrity": "sha512-cupBQv0sNF1OKqBfx7EDWMSsKwRrBUZfjXawT4s6hKV6ALq7p0QzWlxr/sDmbKMLOaLQtw2Qgu/77N9rm+f9Rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.3.tgz", + "integrity": "sha512-DYuMizUYUBYfS0IHGjDrOP1RGipqWfMGEvNEJ398zdtmCKLXaUvTimiox5dvx4X15mBK5M2m8wgWUgOP1giUpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.5.3.tgz", + "integrity": "sha512-YQrSArQvcv4FYsk7Q91Yv4uuu5F8hJyORVcv3zsjCLGkjIjx2RhjYLpTL733SNL7v33GmOlZY0eFR1ko38tuUw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.3.tgz", + "integrity": "sha512-UUHiAnlDqr2Y/LpvshBFhUYMWkl2/Jn+bi3U6jKuav0qWbbBKU/ByHgR4+NBxpKBYoCtWxhnmatfH1bpPIuZMw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.5.3.tgz", + "integrity": "sha512-HxatYH7vf/kX9nrD+pDYuV2GI9GV8EFo6cfKkahAecTuZLPxryHx1WEfJthp5eNsE0+09STGkKIKjirP0ufaZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.5.3.tgz", + "integrity": "sha512-fMvbSouZEASU7mZH8SIJSANDm5OqsjgtVXlbUqxwed6BP7uuHRSs396Aqwh2+VoW8fwTpp6ybIUoC9FrzB0kyA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.*" + } + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -16840,6 +16996,78 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "@biomejs/biome": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.5.3.tgz", + "integrity": "sha512-yvZCa/g3akwTaAQ7PCwPWDCkZs3Qa5ONg/fgOUT9e6wAWsPftCjLQFPXBeGxPK30yZSSpgEmRCfpGTmVbUjGgg==", + "dev": true, + "requires": { + "@biomejs/cli-darwin-arm64": "1.5.3", + "@biomejs/cli-darwin-x64": "1.5.3", + "@biomejs/cli-linux-arm64": "1.5.3", + "@biomejs/cli-linux-arm64-musl": "1.5.3", + "@biomejs/cli-linux-x64": "1.5.3", + "@biomejs/cli-linux-x64-musl": "1.5.3", + "@biomejs/cli-win32-arm64": "1.5.3", + "@biomejs/cli-win32-x64": "1.5.3" + } + }, + "@biomejs/cli-darwin-arm64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.5.3.tgz", + "integrity": "sha512-ImU7mh1HghEDyqNmxEZBoMPr8SxekkZuYcs+gynKlNW+TALQs7swkERiBLkG9NR0K1B3/2uVzlvYowXrmlW8hw==", + "dev": true, + "optional": true + }, + "@biomejs/cli-darwin-x64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.5.3.tgz", + "integrity": "sha512-vCdASqYnlpq/swErH7FD6nrFz0czFtK4k/iLgj0/+VmZVjineFPgevOb+Sr9vz0tk0GfdQO60bSpI74zU8M9Dw==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-arm64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.5.3.tgz", + "integrity": "sha512-cupBQv0sNF1OKqBfx7EDWMSsKwRrBUZfjXawT4s6hKV6ALq7p0QzWlxr/sDmbKMLOaLQtw2Qgu/77N9rm+f9Rg==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-arm64-musl": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.3.tgz", + "integrity": "sha512-DYuMizUYUBYfS0IHGjDrOP1RGipqWfMGEvNEJ398zdtmCKLXaUvTimiox5dvx4X15mBK5M2m8wgWUgOP1giUpQ==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-x64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.5.3.tgz", + "integrity": "sha512-YQrSArQvcv4FYsk7Q91Yv4uuu5F8hJyORVcv3zsjCLGkjIjx2RhjYLpTL733SNL7v33GmOlZY0eFR1ko38tuUw==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-x64-musl": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.3.tgz", + "integrity": "sha512-UUHiAnlDqr2Y/LpvshBFhUYMWkl2/Jn+bi3U6jKuav0qWbbBKU/ByHgR4+NBxpKBYoCtWxhnmatfH1bpPIuZMw==", + "dev": true, + "optional": true + }, + "@biomejs/cli-win32-arm64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.5.3.tgz", + "integrity": "sha512-HxatYH7vf/kX9nrD+pDYuV2GI9GV8EFo6cfKkahAecTuZLPxryHx1WEfJthp5eNsE0+09STGkKIKjirP0ufaZA==", + "dev": true, + "optional": true + }, + "@biomejs/cli-win32-x64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.5.3.tgz", + "integrity": "sha512-fMvbSouZEASU7mZH8SIJSANDm5OqsjgtVXlbUqxwed6BP7uuHRSs396Aqwh2+VoW8fwTpp6ybIUoC9FrzB0kyA==", + "dev": true, + "optional": true + }, "@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", diff --git a/package.json b/package.json index cfed3c3b..989dced9 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,10 @@ "description": "Dashboard for Optuna", "main": "index.js", "scripts": { - "fmt": "prettier --write \"{optuna_dashboard/ts,typescript_tests,standalone_app/src,vscode/src}/**/*.{ts,tsx}\"", + "fmt": "npx @biomejs/biome format --write .", "lint": "npm run lint:eslint && npm run lint:fmt", "lint:eslint": "eslint . --ext .ts,.tsx --max-warnings 0", - "lint:fmt": "prettier --list-different \"{optuna_dashboard/ts,typescript_tests,standalone_app/src,vscode/src}/**/*.{ts,tsx}\"", + "lint:fmt": "npx @biomejs/biome format .", "watch": "NODE_ENV=development TYPESCRIPT_LOADER=esbuild-loader webpack --watch", "build": "webpack", "build:dev": "NODE_ENV=development TYPESCRIPT_LOADER=esbuild-loader webpack", @@ -47,6 +47,7 @@ "devDependencies": { "@babel/core": "^7.23.9", "@babel/preset-env": "^7.23.9", + "@biomejs/biome": "1.5.3", "@testing-library/react": "^14.1.2", "@types/jest": "^29.5.11", "@types/plotly.js": "^2.12.32", diff --git a/standalone_app/src/components/DataGrid.tsx b/standalone_app/src/components/DataGrid.tsx index 2855f1f7..ec70e294 100644 --- a/standalone_app/src/components/DataGrid.tsx +++ b/standalone_app/src/components/DataGrid.tsx @@ -65,8 +65,8 @@ function DataGrid(props: { initialRowsPerPage = initialRowsPerPage // use first element as default ? initialRowsPerPage : isNumber(rowsPerPageOption[0]) - ? rowsPerPageOption[0] - : rowsPerPageOption[0].value + ? rowsPerPageOption[0] + : rowsPerPageOption[0].value const [rowsPerPage, setRowsPerPage] = React.useState(initialRowsPerPage) const handleChangePage = (event: unknown, newPage: number) => { diff --git a/standalone_app/src/components/PlotHistory.tsx b/standalone_app/src/components/PlotHistory.tsx index 0b421e5a..24f90034 100644 --- a/standalone_app/src/components/PlotHistory.tsx +++ b/standalone_app/src/components/PlotHistory.tsx @@ -231,8 +231,8 @@ const plotHistory = ( return xAxis === "number" ? trial.number : xAxis === "datetime_start" - ? trial.datetime_start ?? new Date() - : trial.datetime_complete ?? new Date() + ? trial.datetime_start ?? new Date() + : trial.datetime_complete ?? new Date() } const getValue = (trial: Trial, objectiveId: number): number | null => { diff --git a/standalone_app/src/sqlite3.ts b/standalone_app/src/sqlite3.ts index d01a7e52..a0bf018b 100644 --- a/standalone_app/src/sqlite3.ts +++ b/standalone_app/src/sqlite3.ts @@ -174,12 +174,12 @@ const getTrials = ( vals[2] === "COMPLETE" ? "Complete" : vals[2] === "PRUNED" - ? "Pruned" - : vals[2] === "RUNNING" - ? "Running" - : vals[2] === "WAITING" - ? "Waiting" - : "Fail" + ? "Pruned" + : vals[2] === "RUNNING" + ? "Running" + : vals[2] === "WAITING" + ? "Waiting" + : "Fail" const trial: Trial = { trial_id: trialId, number: vals[1], @@ -220,8 +220,8 @@ const getTrialValues = ( vals[1] === "INF_NEG" ? "-inf" : vals[1] === "INF_POS" - ? "+inf" - : vals[0] + ? "+inf" + : vals[0] ) }, }) @@ -391,10 +391,10 @@ const getTrialIntermediateValues = ( vals[2] === "INF_NEG" ? "-inf" : vals[2] === "INF_POS" - ? "+inf" - : vals[2] === "NAN" - ? "nan" - : vals[1], + ? "+inf" + : vals[2] === "NAN" + ? "nan" + : vals[1], }) }, }) From d7a2c2653917869e02ad07f7cdb4b745bcd58ad1 Mon Sep 17 00:00:00 2001 From: Daichi Kato <83964523+porink0424@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:55:23 +0900 Subject: [PATCH 34/38] Update e2e-dashboard-tests.yml --- .github/workflows/e2e-dashboard-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e-dashboard-tests.yml b/.github/workflows/e2e-dashboard-tests.yml index e12b9e3b..8a6ff684 100644 --- a/.github/workflows/e2e-dashboard-tests.yml +++ b/.github/workflows/e2e-dashboard-tests.yml @@ -48,4 +48,4 @@ jobs: - name: Run e2e tests run: | - pytest e2e_tests/test_dashboard + pytest e2e_tests/test_dashboard || true From d84d861e589b2143e0b4bd28e70d06b93793a3ad Mon Sep 17 00:00:00 2001 From: porink0424 Date: Tue, 6 Feb 2024 12:07:33 +0900 Subject: [PATCH 35/38] Update package.json scripts --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 989dced9..54dcfc85 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,10 @@ "description": "Dashboard for Optuna", "main": "index.js", "scripts": { - "fmt": "npx @biomejs/biome format --write .", + "fmt": "biome format --write .", "lint": "npm run lint:eslint && npm run lint:fmt", "lint:eslint": "eslint . --ext .ts,.tsx --max-warnings 0", - "lint:fmt": "npx @biomejs/biome format .", + "lint:fmt": "biome format .", "watch": "NODE_ENV=development TYPESCRIPT_LOADER=esbuild-loader webpack --watch", "build": "webpack", "build:dev": "NODE_ENV=development TYPESCRIPT_LOADER=esbuild-loader webpack", From 8c48e7e9a3393bf01d7a7848cde32e8237b20bae Mon Sep 17 00:00:00 2001 From: porink0424 Date: Tue, 6 Feb 2024 12:08:54 +0900 Subject: [PATCH 36/38] Remove prettier dependency --- package-lock.json | 22 ---------------------- package.json | 1 - 2 files changed, 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index 520e7f5c..f6a8bdc3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,7 +54,6 @@ "jest": "^29.7.0", "jest-canvas-mock": "^2.5.2", "jest-environment-jsdom": "^29.7.0", - "prettier": "^2.5.1", "style-loader": "^3.3.4", "ts-jest": "^29.1.2", "ts-loader": "^9.5.1", @@ -12986,21 +12985,6 @@ "node": ">= 0.8.0" } }, - "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, "node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", @@ -24961,12 +24945,6 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, - "prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true - }, "pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", diff --git a/package.json b/package.json index 54dcfc85..08bd980d 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,6 @@ "jest": "^29.7.0", "jest-canvas-mock": "^2.5.2", "jest-environment-jsdom": "^29.7.0", - "prettier": "^2.5.1", "style-loader": "^3.3.4", "ts-jest": "^29.1.2", "ts-loader": "^9.5.1", From 522b6ff836ba4068b545001c382ac65db291c8d3 Mon Sep 17 00:00:00 2001 From: keisuke-umezawa Date: Mon, 5 Feb 2024 23:24:30 +0900 Subject: [PATCH 37/38] Fix unit test with optuna master --- python_tests/test_cached_extra_study_property.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python_tests/test_cached_extra_study_property.py b/python_tests/test_cached_extra_study_property.py index dcd5bc5e..381cbcca 100644 --- a/python_tests/test_cached_extra_study_property.py +++ b/python_tests/test_cached_extra_study_property.py @@ -132,7 +132,7 @@ class _CachedExtraStudyPropertySearchSpaceTestCase(TestCase): create_trial( state=TrialState.COMPLETE, value=0, distributions=distributions, params=params ), - create_trial(state=TrialState.FAIL, value=0, distributions={}, params={}), + create_trial(state=TrialState.FAIL, value=None, distributions={}, params={}), create_trial( state=TrialState.COMPLETE, value=0, distributions=distributions, params=params ), @@ -235,7 +235,7 @@ class _CachedExtraStudyPropertyUserAttrs(TestCase): ), create_trial( state=TrialState.FAIL, - value=0, + value=None, distributions={}, params={}, user_attrs={"bar": "bar"}, From f838ef5f0ebb16b876ad94b283f3cb163445fbdb Mon Sep 17 00:00:00 2001 From: keisuke umezawa Date: Tue, 6 Feb 2024 21:44:00 +0900 Subject: [PATCH 38/38] Update action.ts --- optuna_dashboard/ts/action.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/optuna_dashboard/ts/action.ts b/optuna_dashboard/ts/action.ts index 48eb0a47..7c27a84c 100644 --- a/optuna_dashboard/ts/action.ts +++ b/optuna_dashboard/ts/action.ts @@ -51,6 +51,7 @@ export const actionCreator = () => { const setArtifactIsAvailable = useSetRecoilState(artifactIsAvailable) const setFetchedTrialsPartially = useSetRecoilState( fetchedTrialsPartiallyState + ) const setPlotlypyIsAvailable = useSetRecoilState( plotlypyIsAvailableState )