import * as plotly from "plotly.js-dist" import React, { ChangeEvent, FC, useEffect, useState } from "react" import { Grid, FormControl, FormLabel, FormControlLabel, Checkbox, MenuItem, Switch, Select, Radio, RadioGroup, } from "@material-ui/core" import { createStyles, makeStyles, Theme } from "@material-ui/core/styles" const plotDomId = "graph-history" const useStyles = makeStyles((theme: Theme) => createStyles({ formControl: { marginBottom: theme.spacing(2), }, }) ) export const GraphHistory: FC<{ study: StudyDetail | null }> = ({ study = null }) => { const classes = useStyles() const [xAxis, setXAxis] = useState("number") const [objectiveId, setObjectiveId] = useState(0) const [logScale, setLogScale] = useState(false) const [filterCompleteTrial, setFilterCompleteTrial] = useState(false) const [filterPrunedTrial, setFilterPrunedTrial] = useState(false) const handleObjectiveChange = ( event: React.ChangeEvent<{ value: unknown }> ) => { setObjectiveId(event.target.value as number) } const handleXAxisChange = (e: ChangeEvent) => { setXAxis(e.target.value) } const handleLogScaleChange = (e: ChangeEvent) => { e.preventDefault() setLogScale(!logScale) } const handleFilterCompleteChange = (e: ChangeEvent) => { e.preventDefault() setFilterCompleteTrial(!filterCompleteTrial) } const handleFilterPrunedChange = (e: ChangeEvent) => { e.preventDefault() setFilterPrunedTrial(!filterPrunedTrial) } useEffect(() => { if (study !== null) { plotHistory( study, objectiveId, xAxis, logScale, filterCompleteTrial, filterPrunedTrial ) } }, [ study, objectiveId, logScale, xAxis, filterPrunedTrial, filterCompleteTrial, ]) return ( {study !== null && study.directions.length !== 1 ? ( Objective ID: ) : null} Log scale: Filter state: } label="Complete" /> } label="Pruned" /> X-axis: } label="Number" /> } label="Datetime start" /> } label="Datetime complete" />
) } const plotHistory = ( study: StudyDetail, objectiveId: number, xAxis: string, logScale: boolean, filterCompleteTrial: boolean, filterPrunedTrial: boolean ) => { if (document.getElementById(plotDomId) === null) { return } const layout: Partial = { margin: { l: 50, t: 0, r: 50, b: 0, }, yaxis: { type: logScale ? "log" : "linear", }, xaxis: { type: xAxis === "number" ? "linear" : "date", }, showlegend: false, } let filteredTrials = study.trials.filter( (t) => t.state === "Complete" || (t.state === "Pruned" && t.values && t.values.length > 0) ) if (filterCompleteTrial) { filteredTrials = filteredTrials.filter((t) => t.state !== "Complete") } if (filterPrunedTrial) { filteredTrials = filteredTrials.filter((t) => t.state !== "Pruned") } if (filteredTrials.length === 0) { plotly.react(plotDomId, []) return } const trialsForLinePlot: Trial[] = [] let currentBest: number | null = null filteredTrials.forEach((item) => { if (currentBest === null) { currentBest = item.values![objectiveId] trialsForLinePlot.push(item) } else if ( study.directions[objectiveId] === "maximize" && item.values![objectiveId] > currentBest ) { currentBest = item.values![objectiveId] trialsForLinePlot.push(item) } else if ( study.directions[objectiveId] === "minimize" && item.values![objectiveId] < currentBest ) { currentBest = item.values![objectiveId] trialsForLinePlot.push(item) } }) const getAxisX = (trial: Trial): number | Date => { return xAxis === "number" ? trial.number : xAxis === "datetime_start" ? trial.datetime_start! : trial.datetime_complete! } const xForLinePlot = trialsForLinePlot.map(getAxisX) xForLinePlot.push(getAxisX(filteredTrials[filteredTrials.length - 1])) const yForLinePlot = trialsForLinePlot.map( (t: Trial): number => t.values![objectiveId] ) yForLinePlot.push(yForLinePlot[yForLinePlot.length - 1]) const plotData: Partial[] = [ { x: filteredTrials.map(getAxisX), y: filteredTrials.map((t: Trial): number => t.values![objectiveId]), mode: "markers", type: "scatter", }, { x: xForLinePlot, y: yForLinePlot, mode: "lines", type: "scatter", }, ] plotly.react(plotDomId, plotData, layout) }