Merge branch 'main' of github.com:porink0424/optuna-dashboard into feat/jupyterlab-optuna

This commit is contained in:
porink0424
2024-07-10 17:52:59 +09:00
17 changed files with 207 additions and 576 deletions
+12
View File
@@ -9,7 +9,14 @@ on:
- '**.tsx'
- 'optuna_dashboard/package.json'
- 'optuna_dashboard/package-lock.json'
- 'vscode/package.json'
- 'vscode/package-lock.json'
- 'tslib/react/package.json'
- 'tslib/react/package-lock.json'
- 'tslib/storage/package.json'
- 'tslib/storage/package-lock.json'
- 'optuna_dashboard/tsconfig.json'
- 'optuna_dashboard/tsconfig.pkg.json'
- 'optuna_dashboard/webpack.config.js'
jobs:
lint:
@@ -112,6 +119,11 @@ jobs:
npm run build:dev
npm run build:prd
- name: Build optuna_dashboard package (for Jupyter Lab extension)
working-directory: optuna_dashboard
run: |
npm run build:pkg
test-tslib:
name: Run tests
runs-on: ubuntu-latest
+2
View File
@@ -0,0 +1,2 @@
pkg
types
+5 -30
View File
@@ -1,11 +1,11 @@
{
"name": "optuna-dashboard",
"name": "@optuna/optuna-dashboard",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "optuna-dashboard",
"name": "@optuna/optuna-dashboard",
"version": "0.0.1",
"license": "MIT",
"dependencies": {
@@ -19,7 +19,7 @@
"@react-three/drei": "^9.96.4",
"@react-three/fiber": "^8.15.15",
"@tanstack/react-query": "^5.18.1",
"@tanstack/react-table": "^8.16.0",
"@tanstack/react-table": "file:../tslib/react/node_modules/@tanstack/react-table",
"@tanstack/react-virtual": "^3.1.2",
"@types/papaparse": "^5.3.14",
"@types/three": "^0.160.0",
@@ -14278,22 +14278,8 @@
}
},
"node_modules/@tanstack/react-table": {
"version": "8.17.3",
"license": "MIT",
"dependencies": {
"@tanstack/table-core": "8.17.3"
},
"engines": {
"node": ">=12"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": ">=16.8",
"react-dom": ">=16.8"
}
"resolved": "../tslib/react/node_modules/@tanstack/react-table",
"link": true
},
"node_modules/@tanstack/react-virtual": {
"version": "3.5.1",
@@ -14310,17 +14296,6 @@
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/@tanstack/table-core": {
"version": "8.17.3",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/virtual-core": {
"version": "3.5.1",
"license": "MIT",
+5 -3
View File
@@ -1,14 +1,16 @@
{
"name": "optuna-dashboard",
"name": "@optuna/optuna-dashboard",
"private": true,
"version": "0.0.1",
"description": "Dashboard for Optuna",
"main": "index.js",
"main": "pkg/pkg_index.js",
"types": "types/pkg_index.d.ts",
"scripts": {
"watch": "NODE_ENV=development TYPESCRIPT_LOADER=esbuild-loader webpack --watch",
"build": "webpack",
"build:dev": "NODE_ENV=development TYPESCRIPT_LOADER=esbuild-loader webpack",
"build:prd": "NODE_ENV=production webpack",
"build:pkg": "tsc -d --project tsconfig.pkg.json",
"type-check": "tsc --noEmit"
},
"author": "Masashi Shibata",
@@ -24,7 +26,7 @@
"@react-three/drei": "^9.96.4",
"@react-three/fiber": "^8.15.15",
"@tanstack/react-query": "^5.18.1",
"@tanstack/react-table": "^8.16.0",
"@tanstack/react-table": "file:../tslib/react/node_modules/@tanstack/react-table",
"@tanstack/react-virtual": "^3.1.2",
"@types/papaparse": "^5.3.14",
"@types/three": "^0.160.0",
+95 -101
View File
@@ -13,14 +13,10 @@ import { BrowserRouter as Router, Route, Routes } from "react-router-dom"
import { RecoilRoot } from "recoil"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import { APIClientProvider } from "../apiClientProvider"
import { AxiosClient } from "../axiosClient"
import { CompareStudies } from "./CompareStudies"
import { StudyDetail } from "./StudyDetail"
import { StudyList } from "./StudyList"
const axiosAPIClient = new AxiosClient()
const queryClient = new QueryClient({
defaultOptions: {
queries: {
@@ -54,102 +50,100 @@ export const App: FC = () => {
}
return (
<APIClientProvider apiClient={axiosAPIClient}>
<QueryClientProvider client={queryClient}>
<RecoilRoot>
<ThemeProvider theme={theme}>
<CssBaseline />
<Box
component="div"
sx={{
backgroundColor: colorMode === "dark" ? "#121212" : "#ffffff",
width: "100%",
minHeight: "100vh",
}}
>
<SnackbarProvider maxSnack={3}>
<Router>
<Routes>
<Route
path={URL_PREFIX + "/studies/:studyId/analytics"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"analytics"}
/>
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/trials"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"trialList"}
/>
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/trialTable"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"trialTable"}
/>
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/note"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"note"}
/>
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/graph"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"graph"}
/>
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"top"}
/>
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/preference-history"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"preferenceHistory"}
/>
}
/>
<Route
path={URL_PREFIX + "/compare-studies"}
element={
<CompareStudies toggleColorMode={toggleColorMode} />
}
/>
<Route
path={URL_PREFIX + "/"}
element={<StudyList toggleColorMode={toggleColorMode} />}
/>
</Routes>
</Router>
</SnackbarProvider>
</Box>
</ThemeProvider>
</RecoilRoot>
</QueryClientProvider>
</APIClientProvider>
<QueryClientProvider client={queryClient}>
<RecoilRoot>
<ThemeProvider theme={theme}>
<CssBaseline />
<Box
component="div"
sx={{
backgroundColor: colorMode === "dark" ? "#121212" : "#ffffff",
width: "100%",
minHeight: "100vh",
}}
>
<SnackbarProvider maxSnack={3}>
<Router>
<Routes>
<Route
path={URL_PREFIX + "/studies/:studyId/analytics"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"analytics"}
/>
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/trials"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"trialList"}
/>
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/trialTable"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"trialTable"}
/>
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/note"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"note"}
/>
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/graph"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"graph"}
/>
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"top"}
/>
}
/>
<Route
path={URL_PREFIX + "/studies/:studyId/preference-history"}
element={
<StudyDetail
toggleColorMode={toggleColorMode}
page={"preferenceHistory"}
/>
}
/>
<Route
path={URL_PREFIX + "/compare-studies"}
element={
<CompareStudies toggleColorMode={toggleColorMode} />
}
/>
<Route
path={URL_PREFIX + "/"}
element={<StudyList toggleColorMode={toggleColorMode} />}
/>
</Routes>
</Router>
</SnackbarProvider>
</Box>
</ThemeProvider>
</RecoilRoot>
</QueryClientProvider>
)
}
@@ -1,10 +1,10 @@
import ClearIcon from "@mui/icons-material/Clear"
import { Box, Modal, useTheme } from "@mui/material"
import IconButton from "@mui/material/IconButton"
import { DataGrid } from "@optuna/react"
import { useSnackbar } from "notistack"
import Papa from "papaparse"
import React, { useState, useEffect, ReactNode } from "react"
import { DataGrid } from "../DataGrid"
import { Artifact } from "ts/types/optuna"
@@ -13,12 +13,12 @@ import {
import Chip from "@mui/material/Chip"
import Divider from "@mui/material/Divider"
import FormControlLabel from "@mui/material/FormControlLabel"
import Grid from "@mui/material/Grid"
import List from "@mui/material/List"
import ListItem from "@mui/material/ListItem"
import ListItemButton from "@mui/material/ListItemButton"
import ListItemText from "@mui/material/ListItemText"
import ListSubheader from "@mui/material/ListSubheader"
import Grid2 from "@mui/material/Unstable_Grid2"
import * as Optuna from "@optuna/types"
import { useSnackbar } from "notistack"
import React, { FC, useEffect, useMemo, useState } from "react"
@@ -336,21 +336,21 @@ const StudiesGraph: FC<{ studies: StudySummary[] }> = ({ studies }) => {
</CardContent>
</Card>
) : null}
<Grid2 container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
<Grid container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
{showStudyDetails !== null &&
showStudyDetails.length > 0 &&
showStudyDetails.every((s) => s)
? showStudyDetails[0].directions.map((d, i) => (
<Grid2 xs={6} key={i}>
<Grid item xs={6} key={i}>
<Card>
<CardContent>
<GraphEdf studies={showStudyDetails} objectiveId={i} />
</CardContent>
</Card>
</Grid2>
</Grid>
))
: null}
</Grid2>
</Grid>
</Box>
)
}
-383
View File
@@ -1,383 +0,0 @@
import CheckBoxIcon from "@mui/icons-material/CheckBox"
import CheckBoxOutlineBlankIcon from "@mui/icons-material/CheckBoxOutlineBlank"
import FilterListIcon from "@mui/icons-material/FilterList"
import FirstPageIcon from "@mui/icons-material/FirstPage"
import KeyboardArrowLeft from "@mui/icons-material/KeyboardArrowLeft"
import KeyboardArrowRight from "@mui/icons-material/KeyboardArrowRight"
import LastPageIcon from "@mui/icons-material/LastPage"
import {
Box,
IconButton,
Menu,
MenuItem,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TablePagination,
TableRow,
TableSortLabel,
TextField,
useTheme,
} from "@mui/material"
import ListItemIcon from "@mui/material/ListItemIcon"
import Paper from "@mui/material/Paper"
import { TablePaginationActionsProps } from "@mui/material/TablePagination/TablePaginationActions"
import { styled } from "@mui/system"
import React from "react"
import {
ColumnDef,
ColumnFiltersState,
Header,
PaginationState,
SortingState,
flexRender,
getCoreRowModel,
getFacetedRowModel,
getFacetedUniqueValues,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table"
const TableHeaderCellSpan = styled("span")({
display: "inline-flex",
})
const HiddenSpan = styled("span")({
border: 0,
clip: "rect(0 0 0 0)",
height: 1,
margin: -1,
overflow: "hidden",
padding: 0,
position: "absolute",
top: 20,
width: 1,
})
function FilterMenu<T>({
header,
filterChoices,
}: {
header: Header<T, unknown>
filterChoices: string[]
}): React.ReactElement {
const [filterMenuAnchorEl, setFilterMenuAnchorEl] =
React.useState<null | HTMLElement>(null)
return (
<>
<IconButton
size="small"
onClick={(e) => {
setFilterMenuAnchorEl(e.currentTarget)
}}
>
<FilterListIcon fontSize="small" />
</IconButton>
<Menu
anchorEl={filterMenuAnchorEl}
open={filterMenuAnchorEl !== null}
onClose={() => {
setFilterMenuAnchorEl(null)
}}
>
{filterChoices.map((choice) => (
<MenuItem
key={choice}
onClick={() => {
const skippedValues = header.column.getFilterValue() as string[]
const isSkipped = skippedValues.includes(choice)
const newSkippedValues = isSkipped
? skippedValues.filter((v) => v !== choice)
: skippedValues.concat(choice)
header.column.setFilterValue(newSkippedValues)
}}
>
<ListItemIcon>
{header.column.getFilterValue() !== undefined ? (
(header.column.getFilterValue() as string[]).includes(
choice
) ? (
<CheckBoxOutlineBlankIcon color="primary" />
) : (
<CheckBoxIcon color="primary" />
)
) : null}
</ListItemIcon>
{choice ?? "(missing value)"}
</MenuItem>
))}
</Menu>
</>
)
}
function DataGrid<T>({
data,
columns,
initialRowsPerPage,
}: {
data: T[]
columns: ColumnDef<T>[]
initialRowsPerPage?: number
}): React.ReactElement {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
)
const rowsPerPageOptions = [10, 50, 100, { label: "All", value: data.length }]
const [pagination, setPagination] = React.useState<PaginationState>({
pageIndex: 0,
pageSize:
initialRowsPerPage && rowsPerPageOptions.includes(initialRowsPerPage)
? initialRowsPerPage
: 50,
})
const table = useReactTable({
data,
columns,
state: {
columnFilters,
sorting,
pagination,
},
onColumnFiltersChange: setColumnFilters,
onSortingChange: setSorting,
onPaginationChange: setPagination,
getCoreRowModel: getCoreRowModel(),
getFacetedRowModel: getFacetedRowModel(),
getFacetedUniqueValues: getFacetedUniqueValues(),
getSortedRowModel: getSortedRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getFilteredRowModel: getFilteredRowModel(),
autoResetPageIndex: false,
})
return (
<Box component="div" sx={{ width: "100%" }}>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
if (
header.column.getCanFilter() &&
!header.column.getIsFiltered()
) {
header.column.setFilterValue([])
}
const order = header.column.getIsSorted()
const filterChoices = header.column.getCanFilter()
? Array.from(
header.column.getFacetedUniqueValues().keys()
).sort()
: null
return (
<TableCell key={header.id} colSpan={header.colSpan}>
{header.isPlaceholder ? null : (
<TableHeaderCellSpan>
{header.column.getCanSort() ? (
<TableSortLabel
active={order !== false}
direction={order || "asc"}
onClick={header.column.getToggleSortingHandler()}
>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
{order !== null ? (
<HiddenSpan>
{order === "desc"
? "sorted descending"
: "sorted ascending"}
</HiddenSpan>
) : null}
</TableSortLabel>
) : (
flexRender(
header.column.columnDef.header,
header.getContext()
)
)}
{filterChoices !== null ? (
<FilterMenu
header={header}
filterChoices={filterChoices}
/>
) : null}
</TableHeaderCellSpan>
)}
</TableCell>
)
})}
</TableRow>
))}
</TableHead>
<TableBody>
{table.getRowModel().rows.map((row) => {
return (
<TableRow key={row.id}>
{row.getVisibleCells().map((cell) => {
return (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
)
})}
</TableRow>
)
})}
</TableBody>
</Table>
</TableContainer>
<Box component="div" display="flex" alignItems="center">
<TablePagination
rowsPerPageOptions={rowsPerPageOptions}
component="div"
count={table.getFilteredRowModel().rows.length}
rowsPerPage={table.getState().pagination.pageSize}
page={table.getState().pagination.pageIndex}
slotProps={{
select: {
inputProps: { "aria-label": "rows per page" },
native: true,
},
}}
onPageChange={(_, page) => {
table.setPageIndex(page)
}}
onRowsPerPageChange={(e) => {
const size = e.target.value ? Number(e.target.value) : 10
table.setPageSize(size)
}}
ActionsComponent={TablePaginationActions}
/>
{table.getPageCount() > 2 ? (
<PaginationForm1
onPageNumberSubmit={(page) => table.setPageIndex(page)}
maxPageNumber={table.getPageCount()}
/>
) : null}
</Box>
</Box>
)
}
const TablePaginationActions = ({
count,
page,
rowsPerPage,
onPageChange,
}: TablePaginationActionsProps) => {
const theme = useTheme()
const handleFirstPageButtonClick = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
onPageChange(event, 0)
}
const handleBackButtonClick = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
onPageChange(event, page - 1)
}
const handleNextButtonClick = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
onPageChange(event, page + 1)
}
const handleLastPageButtonClick = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1))
}
return (
<Box component="div" sx={{ flexShrink: 0, ml: 2.5 }}>
<IconButton
onClick={handleFirstPageButtonClick}
disabled={page === 0}
aria-label="first page"
>
{theme.direction === "rtl" ? <LastPageIcon /> : <FirstPageIcon />}
</IconButton>
<IconButton
onClick={handleBackButtonClick}
disabled={page === 0}
aria-label="previous page"
>
{theme.direction === "rtl" ? (
<KeyboardArrowRight />
) : (
<KeyboardArrowLeft />
)}
</IconButton>
<IconButton
onClick={handleNextButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="next page"
>
{theme.direction === "rtl" ? (
<KeyboardArrowLeft />
) : (
<KeyboardArrowRight />
)}
</IconButton>
<IconButton
onClick={handleLastPageButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="last page"
>
{theme.direction === "rtl" ? <FirstPageIcon /> : <LastPageIcon />}
</IconButton>
</Box>
)
}
const PaginationForm1: React.FC<{
onPageNumberSubmit: (value: number) => void
maxPageNumber: number
}> = ({ onPageNumberSubmit, maxPageNumber }) => {
// This component is separated from DataGrid to prevent `DataGrid` from re-rendering the page,
// every time any letters are input.
const [specifiedPageText, setSpecifiedPageText] = React.useState("")
const handleSubmitPageNumber = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
const newPageNumber = parseInt(specifiedPageText, 10)
// Page is 0-indexed in `TablePagination`.
onPageNumberSubmit(newPageNumber - 1)
setSpecifiedPageText("") // reset the input field
}
return (
<form onSubmit={handleSubmitPageNumber}>
<TextField
size="small"
label={`Go to Page: n / ${maxPageNumber}`}
value={specifiedPageText}
type="number"
style={{ width: 200 }}
inputProps={{ min: 1, max: maxPageNumber }}
onChange={(e) => {
setSpecifiedPageText(e.target.value)
}}
/>
</form>
)
}
export { DataGrid }
@@ -6,12 +6,12 @@ import {
Typography,
useTheme,
} from "@mui/material"
import Grid2 from "@mui/material/Unstable_Grid2"
import Grid from "@mui/material/Grid"
import { DataGrid } from "@optuna/react"
import * as Optuna from "@optuna/types"
import React, { FC } from "react"
import { useStudyDetailValue, useStudySummaryValue } from "../../state"
import { BestTrialsCard } from "../BestTrialsCard"
import { DataGrid } from "../DataGrid"
import { Contour } from "../GraphContour"
import { ColumnDef, createColumnHelper } from "@tanstack/react-table"
@@ -41,16 +41,16 @@ export const PreferentialAnalytics: FC<{ studyId: number }> = ({ studyId }) => {
component="div"
sx={{ display: "flex", width: "100%", flexDirection: "column" }}
>
<Grid2 container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
<Grid2 xs={14}>
<Grid container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
<Grid item xs={14}>
<Paper elevation={2} sx={{ padding: theme.spacing(2) }}>
<Contour study={studyDetail} />
</Paper>
</Grid2>
<Grid2 xs={6} spacing={2}>
</Grid>
<Grid item xs={6} spacing={2}>
<BestTrialsCard studyDetail={studyDetail} />
</Grid2>
<Grid2 xs={6}>
</Grid>
<Grid item xs={6}>
<Card>
<CardContent
sx={{
@@ -70,8 +70,8 @@ export const PreferentialAnalytics: FC<{ studyId: number }> = ({ studyId }) => {
<DataGrid data={userAttrs} columns={columns} />
</CardContent>
</Card>
</Grid2>
</Grid2>
</Grid>
</Grid>
</Box>
)
}
@@ -8,7 +8,7 @@ import {
Typography,
useTheme,
} from "@mui/material"
import Grid2 from "@mui/material/Unstable_Grid2"
import Grid from "@mui/material/Grid"
import React, { FC, useEffect, useMemo } from "react"
import { Link, useParams } from "react-router-dom"
import { useRecoilValue } from "recoil"
@@ -146,19 +146,19 @@ export const StudyDetail: FC<{
>
Empirical Distribution of the Objective Value
</Typography>
<Grid2 container spacing={2} sx={{ padding: theme.spacing(2) }}>
<Grid container spacing={2} sx={{ padding: theme.spacing(2) }}>
{studyDetail !== null
? studyDetail.directions.map((d, i) => (
<Grid2 xs={6} key={i}>
<Grid item xs={6} key={i}>
<Card>
<CardContent>
<GraphEdf studies={[studyDetail]} objectiveId={i} />
</CardContent>
</Card>
</Grid2>
</Grid>
))
: null}
</Grid2>
</Grid>
</Box>
)
} else if (page === "trialList") {
+20 -20
View File
@@ -8,7 +8,8 @@ import {
useTheme,
} from "@mui/material"
import FormControlLabel from "@mui/material/FormControlLabel"
import Grid2 from "@mui/material/Unstable_Grid2"
import Grid from "@mui/material/Grid"
import { DataGrid } from "@optuna/react"
import * as Optuna from "@optuna/types"
import React, { FC, useState } from "react"
import { useRecoilValue } from "recoil"
@@ -21,7 +22,6 @@ import {
import { artifactIsAvailable } from "../state"
import { StudyArtifactCards } from "./Artifact/StudyArtifactCards"
import { BestTrialsCard } from "./BestTrialsCard"
import { DataGrid } from "./DataGrid"
import { GraphHistory } from "./GraphHistory"
import { GraphHyperparameterImportance } from "./GraphHyperparameterImportances"
import { GraphIntermediateValues } from "./GraphIntermediateValues"
@@ -124,31 +124,31 @@ export const StudyHistory: FC<{ studyId: number }> = ({ studyId }) => {
/>
</CardContent>
</Card>
<Grid2 container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
<Grid2 xs={6}>
<Grid container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
<Grid item xs={6}>
<GraphHyperparameterImportance
studyId={studyId}
study={studyDetail}
graphHeight="450px"
/>
</Grid2>
<Grid2 xs={6}>
</Grid>
<Grid item xs={6}>
<GraphTimeline study={studyDetail} />
</Grid2>
</Grid>
{studyDetail !== null &&
studyDetail.plotly_graph_objects.map((go) => (
<Grid2 xs={6} key={go.id}>
<Grid xs={6} key={go.id}>
<Card>
<CardContent>
<UserDefinedPlot graphObject={go} />
</CardContent>
</Card>
</Grid2>
</Grid>
))}
<Grid2 xs={6} spacing={2}>
<Grid item xs={6}>
<BestTrialsCard studyDetail={studyDetail} />
</Grid2>
<Grid2 xs={6}>
</Grid>
<Grid item xs={6}>
<Card>
<CardContent
sx={{
@@ -168,23 +168,23 @@ export const StudyHistory: FC<{ studyId: number }> = ({ studyId }) => {
<DataGrid data={userAttrs} columns={columns} />
</CardContent>
</Card>
</Grid2>
</Grid>
{studyDetail !== null &&
studyDetail.directions.length === 1 &&
studyDetail.has_intermediate_values ? (
<Grid2 xs={6}>
<Grid item xs={6}>
<GraphIntermediateValues
trials={trials}
includePruned={includePruned}
logScale={logScale}
/>
</Grid2>
</Grid>
) : null}
</Grid2>
</Grid>
{artifactEnabled && studyDetail !== null && (
<Grid2 container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
<Grid2 xs={6}>
<Grid container spacing={2} sx={{ padding: theme.spacing(2) }}>
<Grid item xs={6}>
<Card>
<CardContent
sx={{
@@ -204,8 +204,8 @@ export const StudyHistory: FC<{ studyId: number }> = ({ studyId }) => {
<StudyArtifactCards study={studyDetail} />
</CardContent>
</Card>
</Grid2>
</Grid2>
</Grid>
</Grid>
)}
</Box>
)
@@ -3,9 +3,10 @@ import LinkIcon from "@mui/icons-material/Link"
import { Button, IconButton, useTheme } from "@mui/material"
import React, { FC } from "react"
import { DataGrid } from "@optuna/react"
import { Link } from "react-router-dom"
import { StudyDetail, Trial } from "ts/types/optuna"
import { DataGrid } from "./DataGrid"
import {
ColumnDef,
+7 -1
View File
@@ -1,9 +1,15 @@
import React from "react"
import ReactDOM from "react-dom/client"
import { APIClientProvider } from "./apiClientProvider"
import { AxiosClient } from "./axiosClient"
import { App } from "./components/App"
const axiosAPIClient = new AxiosClient()
ReactDOM.createRoot(document.getElementById("dashboard") as HTMLElement).render(
<React.StrictMode>
<App />
<APIClientProvider apiClient={axiosAPIClient}>
<App />
</APIClientProvider>
</React.StrictMode>
)
+5
View File
@@ -0,0 +1,5 @@
import { APIClientProvider } from "./apiClientProvider"
import { AxiosClient } from "./axiosClient"
import { App } from "./components/App"
export { AxiosClient, APIClientProvider, App }
+15
View File
@@ -0,0 +1,15 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"rootDir": "./ts",
"outDir": "./pkg",
"declaration": true,
"declarationDir": "./types",
},
"files": [
"./ts/pkg_index.tsx",
],
"include": [
"./ts/types/**/*",
],
}
@@ -12,7 +12,7 @@ import {
Typography,
useTheme,
} from "@mui/material"
import Grid2 from "@mui/material/Unstable_Grid2"
import Grid from "@mui/material/Grid"
import {
PlotHistory,
PlotImportance,
@@ -176,8 +176,8 @@ export const StudyDetail: FC<{
<PlotHistory study={study} />
</CardContent>
</Card>
<Grid2 container spacing={0}>
<Grid2 xs={6}>
<Grid container spacing={0}>
<Grid item xs={6}>
<Card sx={{ margin: theme.spacing(2) }}>
<CardContent>
{!!study && (
@@ -185,8 +185,8 @@ export const StudyDetail: FC<{
)}
</CardContent>
</Card>
</Grid2>
<Grid2 xs={6}>
</Grid>
<Grid item xs={6}>
<Card sx={{ margin: theme.spacing(2) }}>
<CardContent>
{!!study && (
@@ -198,8 +198,8 @@ export const StudyDetail: FC<{
)}
</CardContent>
</Card>
</Grid2>
</Grid2>
</Grid>
</Grid>
<Card sx={{ margin: theme.spacing(2) }}>
<CardContent>
{!!study && <TrialTable study={study} initialRowsPerPage={10} />}
+11 -9
View File
@@ -1,15 +1,19 @@
import CheckBoxIcon from "@mui/icons-material/CheckBox"
import CheckBoxOutlineBlankIcon from "@mui/icons-material/CheckBoxOutlineBlank"
import FilterListIcon from "@mui/icons-material/FilterList"
import FirstPageIcon from "@mui/icons-material/FirstPage"
import KeyboardArrowLeft from "@mui/icons-material/KeyboardArrowLeft"
import KeyboardArrowRight from "@mui/icons-material/KeyboardArrowRight"
import LastPageIcon from "@mui/icons-material/LastPage"
import {
CheckBox as CheckBoxIcon,
CheckBoxOutlineBlank as CheckBoxOutlineBlankIcon,
FilterList as FilterListIcon,
FirstPage as FirstPageIcon,
KeyboardArrowLeft,
KeyboardArrowRight,
LastPage as LastPageIcon,
} from "@mui/icons-material"
import {
Box,
IconButton,
ListItem as ListItemIcon,
Menu,
MenuItem,
Paper,
Table,
TableBody,
TableCell,
@@ -21,8 +25,6 @@ import {
TextField,
useTheme,
} from "@mui/material"
import ListItemIcon from "@mui/material/ListItemIcon"
import Paper from "@mui/material/Paper"
import { TablePaginationActionsProps } from "@mui/material/TablePagination/TablePaginationActions"
import { styled } from "@mui/system"
import React from "react"