-
Notifications
You must be signed in to change notification settings - Fork 0
/
demo_callbacks.py
168 lines (139 loc) · 6.17 KB
/
demo_callbacks.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# Copyright 2024 D-Wave
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
from typing import NamedTuple, Union
import dash
from dash import MATCH, ctx
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
from demo_interface import generate_problem_details_table_rows
from src.demo_enums import SolverType
@dash.callback(
Output({"type": "to-collapse-class", "index": MATCH}, "className"),
inputs=[
Input({"type": "collapse-trigger", "index": MATCH}, "n_clicks"),
State({"type": "to-collapse-class", "index": MATCH}, "className"),
],
prevent_initial_call=True,
)
def toggle_left_column(collapse_trigger: int, to_collapse_class: str) -> str:
"""Toggles a 'collapsed' class that hides and shows some aspect of the UI.
Args:
collapse_trigger (int): The (total) number of times a collapse button has been clicked.
to_collapse_class (str): Current class name of the thing to collapse, 'collapsed' if not
visible, empty string if visible.
Returns:
str: The new class name of the thing to collapse.
"""
classes = to_collapse_class.split(" ") if to_collapse_class else []
if "collapsed" in classes:
classes.remove("collapsed")
return " ".join(classes)
return to_collapse_class + " collapsed" if to_collapse_class else "collapsed"
@dash.callback(
Output("input", "children"),
inputs=[
Input("slider", "value"),
],
)
def render_initial_state(slider_value: int) -> str:
"""Runs on load and any time the value of the slider is updated.
Add `prevent_initial_call=True` to skip on load runs.
Args:
slider_value: The value of the slider.
Returns:
str: The content of the input tab.
"""
return f"Put demo input here. The current slider value is {slider_value}."
class RunOptimizationReturn(NamedTuple):
"""Return type for the ``run_optimization`` callback function."""
results: str = dash.no_update
problem_details_table: list = dash.no_update
# Add more return variables here. Return values for callback functions
# with many variables should be returned as a NamedTuple for clarity.
@dash.callback(
# The Outputs below must align with `RunOptimizationReturn`.
Output("results", "children"),
Output("problem-details", "children"),
background=True,
inputs=[
# The first string in the Input/State elements below must match an id in demo_interface.py
# Remove or alter the following id's to match any changes made to demo_interface.py
Input("run-button", "n_clicks"),
State("solver-type-select", "value"),
State("solver-time-limit", "value"),
State("slider", "value"),
State("dropdown", "value"),
State("checklist", "value"),
State("radio", "value"),
],
running=[
(Output("cancel-button", "className"), "", "display-none"), # Show/hide cancel button.
(Output("run-button", "className"), "display-none", ""), # Hides run button while running.
(Output("results-tab", "disabled"), True, False), # Disables results tab while running.
(Output("results-tab", "label"), "Loading...", "Results"),
(Output("tabs", "value"), "input-tab", "input-tab"), # Switch to input tab while running.
(Output("run-in-progress", "data"), True, False), # Can block certain callbacks.
],
cancel=[Input("cancel-button", "n_clicks")],
prevent_initial_call=True,
)
def run_optimization(
# The parameters below must match the `Input` and `State` variables found
# in the `inputs` list above.
run_click: int,
solver_type: Union[SolverType, int],
time_limit: float,
slider_value: int,
dropdown_value: int,
checklist_value: list,
radio_value: int,
) -> RunOptimizationReturn:
"""Runs the optimization and updates UI accordingly.
This is the main function which is called when the ``Run Optimization`` button is clicked.
This function takes in all form values and runs the optimization, updates the run/cancel
buttons, deactivates (and reactivates) the results tab, and updates all relevant HTML
components.
Args:
run_click: The (total) number of times the run button has been clicked.
solver_type: The solver to use for the optimization run defined by SolverType in demo_enums.py.
time_limit: The solver time limit.
slider_value: The value of the slider.
dropdown_value: The value of the dropdown.
checklist_value: A list of the values of the checklist.
radio_value: The value of the radio.
Returns:
A NamedTuple (RunOptimizationReturn) containing all outputs to be used when updating the HTML
template (in ``demo_interface.py``). These are:
results: The results to display in the results tab.
problem-details: List of the table rows for the problem details table.
"""
# Only run optimization code if this function was triggered by a click on `run-button`.
# Setting `Input` as exclusively `run-button` and setting `prevent_initial_call=True`
# also accomplishes this.
if run_click == 0 or ctx.triggered_id != "run-button":
raise PreventUpdate
solver_type = SolverType(solver_type)
###########################
### YOUR CODE GOES HERE ###
###########################
# Generates a list of table rows for the problem details table.
problem_details_table = generate_problem_details_table_rows(
solver=solver_type.label,
time_limit=time_limit,
)
return RunOptimizationReturn(
results="Put demo results here.",
problem_details_table=problem_details_table,
)