Implement register_user_attr_form_widgets

This commit is contained in:
Kenshin Abe
2023-03-10 16:18:08 +09:00
parent 61b18460db
commit c7221c1ea4
8 changed files with 38 additions and 3 deletions
+1
View File
@@ -7,6 +7,7 @@ from ._objective_form_widget import ObjectiveSliderWidget # noqa
from ._objective_form_widget import ObjectiveTextInputWidget # noqa
from ._objective_form_widget import ObjectiveUserAttrRef # noqa
from ._objective_form_widget import register_objective_form_widgets # noqa
from ._objective_form_widget import register_user_attr_form_widgets # noqa
__version__ = "0.9.0b6"
+3
View File
@@ -34,6 +34,7 @@ from ._bottle_util import BottleViewReturn
from ._bottle_util import json_api_view
from ._cached_extra_study_property import get_cached_extra_study_property
from ._importance import get_param_importance_from_trials_cache
from ._objective_form_widget import SYSTEM_ATTR_OUTPUT_TYPE_KEY
from ._pareto_front import get_pareto_front_trials
from ._serializer import serialize_study_detail
from ._serializer import serialize_study_summary
@@ -357,6 +358,7 @@ def create_app(
union_user_attrs,
has_intermediate_values,
) = get_cached_extra_study_property(study_id, trials)
form_widgets_output_type = storage.get_study_system_attrs(study_id).get(SYSTEM_ATTR_OUTPUT_TYPE_KEY)
return serialize_study_detail(
summary,
best_trials,
@@ -365,6 +367,7 @@ def create_app(
union,
union_user_attrs,
has_intermediate_values,
form_widgets_output_type,
)
@app.get("/api/studies/<study_id:int>/param_importances")
@@ -111,6 +111,7 @@ ObjectiveFormWidget = Union[
ObjectiveChoiceWidget, ObjectiveSliderWidget, ObjectiveTextInputWidget, ObjectiveUserAttrRef
]
SYSTEM_ATTR_KEY = "dashboard:objective_form_widgets:v1"
SYSTEM_ATTR_OUTPUT_TYPE_KEY = "dashboard:form_widgets_output_type:v1"
def register_objective_form_widgets(
@@ -120,6 +121,15 @@ def register_objective_form_widgets(
raise ValueError("The length of actions must be the same with the number of objectives.")
widget_dicts = [w.to_dict() for w in widgets]
study._storage.set_study_system_attr(study._study_id, SYSTEM_ATTR_KEY, widget_dicts)
study._storage.set_study_system_attr(study._study_id, SYSTEM_ATTR_OUTPUT_TYPE_KEY, "objective")
def register_user_attr_form_widgets(
study: optuna.Study, widgets: list[ObjectiveFormWidget]
) -> None:
widget_dicts = [w.to_dict() for w in widgets]
study._storage.set_study_system_attr(study._study_id, SYSTEM_ATTR_KEY, widget_dicts)
study._storage.set_study_system_attr(study._study_id, SYSTEM_ATTR_OUTPUT_TYPE_KEY, "user_attr")
def get_objective_form_widgets_json(
+3
View File
@@ -2,6 +2,7 @@ from __future__ import annotations
import json
from typing import Any
from typing import Optional
from typing import TYPE_CHECKING
from typing import Union
@@ -121,6 +122,7 @@ def serialize_study_detail(
union: list[tuple[str, BaseDistribution]],
union_user_attrs: list[tuple[str, bool]],
has_intermediate_values: bool,
form_widgets_output_type: Optional[str],
) -> dict[str, Any]:
serialized: dict[str, Any] = {
"name": summary.study_name,
@@ -147,6 +149,7 @@ def serialize_study_detail(
objective_form_widgets = get_objective_form_widgets_json(system_attrs)
if objective_form_widgets:
serialized["objective_form_widgets"] = objective_form_widgets
serialized["form_widgets_output_type"] = form_widgets_output_type
return serialized
+2
View File
@@ -68,6 +68,7 @@ interface StudyDetailResponse {
note: Note
objective_names?: string[]
objective_form_widgets?: ObjectiveFormWidget[]
form_widgets_output_type?: string
}
export const getStudyDetailAPI = (
@@ -101,6 +102,7 @@ export const getStudyDetailAPI = (
note: res.data.note,
objective_names: res.data.objective_names,
objective_form_widgets: res.data.objective_form_widgets,
form_widgets_output_type: res.data.form_widgets_output_type,
}
})
}
@@ -21,7 +21,8 @@ export const ObjectiveForm: FC<{
directions: StudyDirection[]
names: string[]
widgets: ObjectiveFormWidget[]
}> = ({ trial, directions, names, widgets }) => {
outputType: string
}> = ({ trial, directions, names, widgets, outputType }) => {
const theme = useTheme()
const action = actionCreator()
const [values, setValues] = useState<(number | null)[]>(
@@ -64,8 +65,16 @@ export const ObjectiveForm: FC<{
const handleSubmit = (e: React.MouseEvent<HTMLButtonElement>): void => {
e.preventDefault()
const user_attrs = Object.fromEntries(widgets.map((widget, i) => [widget.description, values[i]]))
action.saveTrialUserAttrs(trial.study_id, trial.trial_id, user_attrs)
if (outputType == "objective") {
const filtered = values.filter<number>((v): v is number => v !== null)
if (filtered.length !== directions.length) {
return
}
action.tellTrial(trial.study_id, trial.trial_id, "Complete", filtered)
} else if (outputType == "user_attr") {
const user_attrs = Object.fromEntries(widgets.map((widget, i) => [widget.description, values[i]]))
action.saveTrialUserAttrs(trial.study_id, trial.trial_id, user_attrs)
}
}
const getObjectiveName = (i: number): string => {
@@ -144,12 +144,14 @@ const TrialListDetail: FC<{
directions: StudyDirection[]
objectiveNames: string[]
objectiveFormWidgets: ObjectiveFormWidget[]
formWigetsOutputType: string
}> = ({
trial,
isBestTrial,
directions,
objectiveNames,
objectiveFormWidgets,
formWigetsOutputType
}) => {
const theme = useTheme()
const artifactEnabled = useRecoilValue<boolean>(artifactIsAvailable)
@@ -297,6 +299,7 @@ const TrialListDetail: FC<{
directions={directions}
names={objectiveNames}
widgets={objectiveFormWidgets}
outputType={formWigetsOutputType}
/>
)}
{trial.state === "Complete" && directions.length > 0 && (
@@ -816,6 +819,9 @@ export const TrialList: FC<{ studyDetail: StudyDetail | null }> = ({
objectiveFormWidgets={
studyDetail?.objective_form_widgets || []
}
formWigetsOutputType={
studyDetail?.form_widgets_output_type || ""
}
/>
))}
</Box>
+1
View File
@@ -176,6 +176,7 @@ type StudyDetail = {
note: Note
objective_names?: string[]
objective_form_widgets?: ObjectiveFormWidget[]
form_widgets_output_type?: string
}
type StudyDetails = {