Spaces:
Sleeping
Sleeping
[FEAT/FIX] Tab3: adaptive slider precision, hide Other resources, show hidden secondary hints, filter inactive methods
Browse files- tabs/tab3_coefficients.py +99 -34
tabs/tab3_coefficients.py
CHANGED
|
@@ -2,7 +2,8 @@ import pandas as pd
|
|
| 2 |
import streamlit as st
|
| 3 |
|
| 4 |
from config.config import (method_groups, method_order, resource_groups,
|
| 5 |
-
resource_order, secondary_resources, resource_unit_map, CO2_UNIT
|
|
|
|
| 6 |
from utils.ui_helpers import format_efficiency_summary, show_bar
|
| 7 |
from utils.data_utils import strip_unit_suffix, get_resource_to_group
|
| 8 |
|
|
@@ -15,22 +16,50 @@ def normalize_costs(costs_dict: dict) -> dict:
|
|
| 15 |
def get_slider_params(conf: dict) -> tuple:
|
| 16 |
"""Derive slider step size and display format from a coefficient config dict.
|
| 17 |
|
|
|
|
|
|
|
|
|
|
| 18 |
Args:
|
| 19 |
-
conf (dict): slider config with
|
| 20 |
|
| 21 |
Returns:
|
| 22 |
tuple[float, str]: (step, fmt) where step is the slider increment and
|
| 23 |
fmt is a printf-style format string for display.
|
| 24 |
"""
|
| 25 |
min_coeff = conf["min"]
|
| 26 |
-
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
elif min_coeff < 1:
|
| 29 |
-
|
| 30 |
elif min_coeff < 100:
|
| 31 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
else:
|
| 33 |
-
|
|
|
|
|
|
|
| 34 |
|
| 35 |
|
| 36 |
def is_method_enabled(method, resource, enabled_methods):
|
|
@@ -167,9 +196,9 @@ def render_standard_resource_row(method, r, conf, display_label, enabled_methods
|
|
| 167 |
|
| 168 |
is_secondary = (method, r) in secondary_resources
|
| 169 |
step, fmt = get_slider_params(conf)
|
| 170 |
-
toggle_key = f"toggle_{method}_{r}".replace(" ", "_")
|
| 171 |
-
slider_key = f"slider_{method}_{r}".replace(" ", "_")
|
| 172 |
-
manual_key = f"manual_{method}_{r}".replace(" ", "_")
|
| 173 |
current_val = normalize_costs(st.session_state.costs.get(method, {})).get(r, 0.0)
|
| 174 |
if is_secondary:
|
| 175 |
if toggle_key not in st.session_state:
|
|
@@ -190,15 +219,15 @@ def render_standard_resource_row(method, r, conf, display_label, enabled_methods
|
|
| 190 |
st.session_state.costs[method][r] = conf["median"]
|
| 191 |
if st.session_state.get("resource_caps", {}).get(r, 0) <= 0:
|
| 192 |
if has_custom_batch:
|
| 193 |
-
st.
|
| 194 |
f"No available quantity set for **{r}** in Resource Inputs tab.",
|
| 195 |
-
icon=":material/
|
| 196 |
)
|
| 197 |
else:
|
| 198 |
-
st.
|
| 199 |
f"No available quantity set for **{r}** in Resource Inputs tab: "
|
| 200 |
f"**{method}** won't be used in the optimization.",
|
| 201 |
-
icon=":material/
|
| 202 |
)
|
| 203 |
return
|
| 204 |
|
|
@@ -208,15 +237,15 @@ def render_standard_resource_row(method, r, conf, display_label, enabled_methods
|
|
| 208 |
st.session_state[manual_key] = st.session_state[slider_key]
|
| 209 |
if st.session_state.get("resource_caps", {}).get(r, 0) <= 0:
|
| 210 |
if has_custom_batch:
|
| 211 |
-
st.
|
| 212 |
f"No available quantity set for **{r}** in Resource Inputs tab.",
|
| 213 |
-
icon=":material/
|
| 214 |
)
|
| 215 |
else:
|
| 216 |
-
st.
|
| 217 |
f"No available quantity set for **{r}** in Resource Inputs tab: "
|
| 218 |
f"**{method}** won't be used in the optimization.",
|
| 219 |
-
icon=":material/
|
| 220 |
)
|
| 221 |
|
| 222 |
col1, col2 = st.columns([3, 1])
|
|
@@ -225,13 +254,13 @@ def render_standard_resource_row(method, r, conf, display_label, enabled_methods
|
|
| 225 |
label=display_label,
|
| 226 |
min_value=conf["min"], max_value=conf["max"], step=step, format=fmt,
|
| 227 |
key=slider_key,
|
| 228 |
-
on_change=make_sync_s_to_m(slider_key, manual_key)
|
| 229 |
)
|
| 230 |
with col2:
|
| 231 |
st.number_input(
|
| 232 |
label="label", label_visibility="collapsed",
|
| 233 |
key=manual_key, help="Manual override (optional, any value)",
|
| 234 |
-
format=fmt, value=None, placeholder=str(round(slider_val,
|
| 235 |
on_change=make_sync_m_to_s(slider_key, manual_key, conf["min"], conf["max"]),
|
| 236 |
)
|
| 237 |
|
|
@@ -259,9 +288,9 @@ def render_custom_resource_row(method, r, conf, enabled_methods, custom_resource
|
|
| 259 |
|
| 260 |
is_sec = is_custom_secondary(method, r, custom_resource_to_sub_group)
|
| 261 |
step, fmt = get_slider_params(conf)
|
| 262 |
-
toggle_key = f"toggle_{method}_{r}".replace(" ", "_")
|
| 263 |
-
slider_key = f"slider_{method}_{r}".replace(" ", "_")
|
| 264 |
-
manual_key = f"manual_{method}_{r}".replace(" ", "_")
|
| 265 |
current_val = st.session_state.costs.get(method, {}).get(r, 0.0 if is_sec else conf["median"])
|
| 266 |
|
| 267 |
if is_sec:
|
|
@@ -314,7 +343,7 @@ def render_custom_resource_row(method, r, conf, enabled_methods, custom_resource
|
|
| 314 |
st.number_input(
|
| 315 |
label="label", label_visibility="collapsed",
|
| 316 |
key=manual_key, help="Manual override (optional, any value)",
|
| 317 |
-
format=fmt, value=None, placeholder=str(round(slider_val,
|
| 318 |
on_change=make_sync_m_to_s(slider_key, manual_key, conf["min"], conf["max"]),
|
| 319 |
)
|
| 320 |
|
|
@@ -350,13 +379,32 @@ def panel_method_editor(
|
|
| 350 |
method_sliders = cost_sliders_norm.get(method, {})
|
| 351 |
custom_for_method = custom_sliders_by_method.get(method, {})
|
| 352 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 353 |
for group_name, rlist in resource_groups.items():
|
| 354 |
-
used = [r for r in rlist if r in method_sliders]
|
| 355 |
custom_in_group = [
|
| 356 |
r for r in custom_for_method
|
| 357 |
if custom_resource_to_group.get(r) == group_name
|
| 358 |
]
|
| 359 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 360 |
continue
|
| 361 |
|
| 362 |
st.markdown(f'<p class="crra-group-name">{group_name}</p>', unsafe_allow_html=True)
|
|
@@ -375,16 +423,23 @@ def panel_method_editor(
|
|
| 375 |
enabled_methods, custom_resource_to_sub_group, custom_resources
|
| 376 |
)
|
| 377 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 378 |
if st.button("Reset selected method", key="btn-reset-method", icon=":material/reset_settings:"):
|
| 379 |
for r, conf in cost_sliders_norm.get(method, {}).items():
|
| 380 |
is_secondary = (method, r) in secondary_resources
|
| 381 |
st.session_state.costs[method][r] = 0.0 if is_secondary else conf["median"]
|
| 382 |
for prefix in ["slider", "manual", "toggle"]:
|
| 383 |
-
st.session_state.pop(f"{prefix}_{method}_{r}".replace(" ", "_")
|
| 384 |
for r, conf in custom_sliders_by_method.get(method, {}).items():
|
| 385 |
st.session_state.costs.setdefault(method, {})[r] = conf["median"]
|
| 386 |
for prefix in ["slider", "manual"]:
|
| 387 |
-
st.session_state.pop(f"{prefix}_{method}_{r}".replace(" ", "_")
|
| 388 |
st.success(f"{method} reset to default values.")
|
| 389 |
st.rerun()
|
| 390 |
|
|
@@ -414,7 +469,7 @@ def panel_summary_table(
|
|
| 414 |
for cat, resources in resource_groups.items()
|
| 415 |
for r in resources
|
| 416 |
}
|
| 417 |
-
all_resource_columns = resource_order + sorted(custom_resource_names)
|
| 418 |
|
| 419 |
df_default = pd.DataFrame(index=method_order, columns=all_resource_columns)
|
| 420 |
df_current = pd.DataFrame(index=method_order, columns=all_resource_columns)
|
|
@@ -476,9 +531,9 @@ def render_tab(cost_sliders):
|
|
| 476 |
unsafe_allow_html=True,
|
| 477 |
)
|
| 478 |
with st.container(key="warning_resources"):
|
| 479 |
-
st.
|
| 480 |
"Red cells in the table highlight coefficients modified from their **default median values**",
|
| 481 |
-
icon=":material/
|
| 482 |
)
|
| 483 |
|
| 484 |
enabled_methods = st.session_state.get("enabled_methods", {})
|
|
@@ -498,7 +553,17 @@ def render_tab(cost_sliders):
|
|
| 498 |
custom_resource_to_group,
|
| 499 |
) = build_custom_slider_index(cost_sliders_norm, custom_resources)
|
| 500 |
|
| 501 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 502 |
method_lookup = {label: label.split(" | ", 1)[1] for label in method_choices}
|
| 503 |
selected_label = st.selectbox("Select a method:", method_choices, key="crra-select")
|
| 504 |
|
|
@@ -507,14 +572,14 @@ def render_tab(cost_sliders):
|
|
| 507 |
for r, conf in sliders.items():
|
| 508 |
st.session_state.costs[m][r] = 0.0 if (m, r) in secondary_resources else conf["median"]
|
| 509 |
for prefix in ["slider", "manual", "toggle"]:
|
| 510 |
-
st.session_state.pop(f"{prefix}_{m}_{r}".replace(" ", "_")
|
| 511 |
for m, sliders in custom_sliders_by_method.items():
|
| 512 |
for r, conf in sliders.items():
|
| 513 |
st.session_state.costs.setdefault(m, {})[r] = (
|
| 514 |
0.0 if is_custom_secondary(m, r, custom_resource_to_sub_group) else conf["median"]
|
| 515 |
)
|
| 516 |
for prefix in ["slider", "manual", "toggle"]:
|
| 517 |
-
st.session_state.pop(f"{prefix}_{m}_{r}".replace(" ", "_")
|
| 518 |
st.success("All methods reset to default values.")
|
| 519 |
st.rerun()
|
| 520 |
|
|
|
|
| 2 |
import streamlit as st
|
| 3 |
|
| 4 |
from config.config import (method_groups, method_order, resource_groups,
|
| 5 |
+
resource_order, secondary_resources, resource_unit_map, CO2_UNIT,
|
| 6 |
+
hidden_resource_names)
|
| 7 |
from utils.ui_helpers import format_efficiency_summary, show_bar
|
| 8 |
from utils.data_utils import strip_unit_suffix, get_resource_to_group
|
| 9 |
|
|
|
|
| 16 |
def get_slider_params(conf: dict) -> tuple:
|
| 17 |
"""Derive slider step size and display format from a coefficient config dict.
|
| 18 |
|
| 19 |
+
Format is driven by min (display precision); step is driven by range
|
| 20 |
+
(usability) and floored at 1e-06 (Streamlit's hard lower limit).
|
| 21 |
+
|
| 22 |
Args:
|
| 23 |
+
conf (dict): slider config with keys "min", "median", "max".
|
| 24 |
|
| 25 |
Returns:
|
| 26 |
tuple[float, str]: (step, fmt) where step is the slider increment and
|
| 27 |
fmt is a printf-style format string for display.
|
| 28 |
"""
|
| 29 |
min_coeff = conf["min"]
|
| 30 |
+
coeff_range = conf["max"] - min_coeff
|
| 31 |
+
|
| 32 |
+
# Format: enough decimals to show the minimum value without scientific notation
|
| 33 |
+
if min_coeff < 1e-10:
|
| 34 |
+
fmt = "%.11f"
|
| 35 |
+
elif min_coeff < 1e-08:
|
| 36 |
+
fmt = "%.9f"
|
| 37 |
+
elif min_coeff < 1e-05:
|
| 38 |
+
fmt = "%.6f"
|
| 39 |
+
elif min_coeff < 0.01:
|
| 40 |
+
fmt = "%.4f"
|
| 41 |
elif min_coeff < 1:
|
| 42 |
+
fmt = "%.3f"
|
| 43 |
elif min_coeff < 100:
|
| 44 |
+
fmt = "%.2f"
|
| 45 |
+
else:
|
| 46 |
+
fmt = "%.0f"
|
| 47 |
+
|
| 48 |
+
# Step: ~1/1000 of the range, floored at 1e-06 (Streamlit minimum)
|
| 49 |
+
if coeff_range < 0.001:
|
| 50 |
+
step = 1e-06
|
| 51 |
+
elif coeff_range < 0.1:
|
| 52 |
+
step = 0.0001
|
| 53 |
+
elif coeff_range < 1:
|
| 54 |
+
step = 0.001
|
| 55 |
+
elif coeff_range < 10:
|
| 56 |
+
step = 0.01
|
| 57 |
+
elif coeff_range < 100:
|
| 58 |
+
step = 0.1
|
| 59 |
else:
|
| 60 |
+
step = 1.0
|
| 61 |
+
|
| 62 |
+
return step, fmt
|
| 63 |
|
| 64 |
|
| 65 |
def is_method_enabled(method, resource, enabled_methods):
|
|
|
|
| 196 |
|
| 197 |
is_secondary = (method, r) in secondary_resources
|
| 198 |
step, fmt = get_slider_params(conf)
|
| 199 |
+
toggle_key = f"toggle_{method}_{r}".replace(" ", "_")
|
| 200 |
+
slider_key = f"slider_{method}_{r}".replace(" ", "_")
|
| 201 |
+
manual_key = f"manual_{method}_{r}".replace(" ", "_")
|
| 202 |
current_val = normalize_costs(st.session_state.costs.get(method, {})).get(r, 0.0)
|
| 203 |
if is_secondary:
|
| 204 |
if toggle_key not in st.session_state:
|
|
|
|
| 219 |
st.session_state.costs[method][r] = conf["median"]
|
| 220 |
if st.session_state.get("resource_caps", {}).get(r, 0) <= 0:
|
| 221 |
if has_custom_batch:
|
| 222 |
+
st.warning(
|
| 223 |
f"No available quantity set for **{r}** in Resource Inputs tab.",
|
| 224 |
+
icon=":material/warning:",
|
| 225 |
)
|
| 226 |
else:
|
| 227 |
+
st.warning(
|
| 228 |
f"No available quantity set for **{r}** in Resource Inputs tab: "
|
| 229 |
f"**{method}** won't be used in the optimization.",
|
| 230 |
+
icon=":material/warning:",
|
| 231 |
)
|
| 232 |
return
|
| 233 |
|
|
|
|
| 237 |
st.session_state[manual_key] = st.session_state[slider_key]
|
| 238 |
if st.session_state.get("resource_caps", {}).get(r, 0) <= 0:
|
| 239 |
if has_custom_batch:
|
| 240 |
+
st.warning(
|
| 241 |
f"No available quantity set for **{r}** in Resource Inputs tab.",
|
| 242 |
+
icon=":material/warning:",
|
| 243 |
)
|
| 244 |
else:
|
| 245 |
+
st.warning(
|
| 246 |
f"No available quantity set for **{r}** in Resource Inputs tab: "
|
| 247 |
f"**{method}** won't be used in the optimization.",
|
| 248 |
+
icon=":material/warning:",
|
| 249 |
)
|
| 250 |
|
| 251 |
col1, col2 = st.columns([3, 1])
|
|
|
|
| 254 |
label=display_label,
|
| 255 |
min_value=conf["min"], max_value=conf["max"], step=step, format=fmt,
|
| 256 |
key=slider_key,
|
| 257 |
+
on_change=make_sync_s_to_m(slider_key, manual_key)
|
| 258 |
)
|
| 259 |
with col2:
|
| 260 |
st.number_input(
|
| 261 |
label="label", label_visibility="collapsed",
|
| 262 |
key=manual_key, help="Manual override (optional, any value)",
|
| 263 |
+
format=fmt, value=None, placeholder=str(round(slider_val, 6)),
|
| 264 |
on_change=make_sync_m_to_s(slider_key, manual_key, conf["min"], conf["max"]),
|
| 265 |
)
|
| 266 |
|
|
|
|
| 288 |
|
| 289 |
is_sec = is_custom_secondary(method, r, custom_resource_to_sub_group)
|
| 290 |
step, fmt = get_slider_params(conf)
|
| 291 |
+
toggle_key = f"toggle_{method}_{r}".replace(" ", "_")
|
| 292 |
+
slider_key = f"slider_{method}_{r}".replace(" ", "_")
|
| 293 |
+
manual_key = f"manual_{method}_{r}".replace(" ", "_")
|
| 294 |
current_val = st.session_state.costs.get(method, {}).get(r, 0.0 if is_sec else conf["median"])
|
| 295 |
|
| 296 |
if is_sec:
|
|
|
|
| 343 |
st.number_input(
|
| 344 |
label="label", label_visibility="collapsed",
|
| 345 |
key=manual_key, help="Manual override (optional, any value)",
|
| 346 |
+
format=fmt, value=None, placeholder=str(round(slider_val, 6)),
|
| 347 |
on_change=make_sync_m_to_s(slider_key, manual_key, conf["min"], conf["max"]),
|
| 348 |
)
|
| 349 |
|
|
|
|
| 379 |
method_sliders = cost_sliders_norm.get(method, {})
|
| 380 |
custom_for_method = custom_sliders_by_method.get(method, {})
|
| 381 |
|
| 382 |
+
primary_resources = [r for r in method_sliders if (method, r) not in secondary_resources]
|
| 383 |
+
if primary_resources and all(r in hidden_resource_names for r in primary_resources) and not custom_for_method:
|
| 384 |
+
required = [r for r in primary_resources if r in hidden_resource_names]
|
| 385 |
+
optional = [r for r in method_sliders if r in hidden_resource_names and (method, r) in secondary_resources]
|
| 386 |
+
req_list = "\n".join(f"- **{r}** *(required)*" for r in required)
|
| 387 |
+
opt_list = "\n".join(f"- **{r}** *(optional)*" for r in optional) if optional else ""
|
| 388 |
+
body = f"To use this method, add a new resource in the **Resource inputs** tab:\n\n{req_list}"
|
| 389 |
+
if opt_list:
|
| 390 |
+
body += f"\n{opt_list}"
|
| 391 |
+
st.info(body, icon=":material/info:")
|
| 392 |
+
return
|
| 393 |
+
|
| 394 |
for group_name, rlist in resource_groups.items():
|
| 395 |
+
used = [r for r in rlist if r in method_sliders and r not in hidden_resource_names]
|
| 396 |
custom_in_group = [
|
| 397 |
r for r in custom_for_method
|
| 398 |
if custom_resource_to_group.get(r) == group_name
|
| 399 |
]
|
| 400 |
+
hidden_secondary_in_group = [
|
| 401 |
+
r for r in rlist
|
| 402 |
+
if r in method_sliders
|
| 403 |
+
and r in hidden_resource_names
|
| 404 |
+
and (method, r) in secondary_resources
|
| 405 |
+
and not any(custom_resource_to_sub_group.get(cr) == r for cr in custom_for_method)
|
| 406 |
+
]
|
| 407 |
+
if not used and not custom_in_group and not hidden_secondary_in_group:
|
| 408 |
continue
|
| 409 |
|
| 410 |
st.markdown(f'<p class="crra-group-name">{group_name}</p>', unsafe_allow_html=True)
|
|
|
|
| 423 |
enabled_methods, custom_resource_to_sub_group, custom_resources
|
| 424 |
)
|
| 425 |
|
| 426 |
+
for r in hidden_secondary_in_group:
|
| 427 |
+
st.info(
|
| 428 |
+
f"**{r}** can be used as an optional secondary resource for this method. "
|
| 429 |
+
f"Add a custom resource of type **{r}** in the **Resource inputs** tab to activate it.",
|
| 430 |
+
icon=":material/add_circle:",
|
| 431 |
+
)
|
| 432 |
+
|
| 433 |
if st.button("Reset selected method", key="btn-reset-method", icon=":material/reset_settings:"):
|
| 434 |
for r, conf in cost_sliders_norm.get(method, {}).items():
|
| 435 |
is_secondary = (method, r) in secondary_resources
|
| 436 |
st.session_state.costs[method][r] = 0.0 if is_secondary else conf["median"]
|
| 437 |
for prefix in ["slider", "manual", "toggle"]:
|
| 438 |
+
st.session_state.pop(f"{prefix}_{method}_{r}".replace(" ", "_"), None)
|
| 439 |
for r, conf in custom_sliders_by_method.get(method, {}).items():
|
| 440 |
st.session_state.costs.setdefault(method, {})[r] = conf["median"]
|
| 441 |
for prefix in ["slider", "manual"]:
|
| 442 |
+
st.session_state.pop(f"{prefix}_{method}_{r}".replace(" ", "_"), None)
|
| 443 |
st.success(f"{method} reset to default values.")
|
| 444 |
st.rerun()
|
| 445 |
|
|
|
|
| 469 |
for cat, resources in resource_groups.items()
|
| 470 |
for r in resources
|
| 471 |
}
|
| 472 |
+
all_resource_columns = [r for r in resource_order if r not in hidden_resource_names] + sorted(custom_resource_names)
|
| 473 |
|
| 474 |
df_default = pd.DataFrame(index=method_order, columns=all_resource_columns)
|
| 475 |
df_current = pd.DataFrame(index=method_order, columns=all_resource_columns)
|
|
|
|
| 531 |
unsafe_allow_html=True,
|
| 532 |
)
|
| 533 |
with st.container(key="warning_resources"):
|
| 534 |
+
st.info(
|
| 535 |
"Red cells in the table highlight coefficients modified from their **default median values**",
|
| 536 |
+
icon=":material/info:",
|
| 537 |
)
|
| 538 |
|
| 539 |
enabled_methods = st.session_state.get("enabled_methods", {})
|
|
|
|
| 553 |
custom_resource_to_group,
|
| 554 |
) = build_custom_slider_index(cost_sliders_norm, custom_resources)
|
| 555 |
|
| 556 |
+
constraints = st.session_state.get("constraints", {})
|
| 557 |
+
active_methods = {m for m, c in constraints.items() if c.get("active", True)}
|
| 558 |
+
method_choices = [
|
| 559 |
+
f"{g} | {m}"
|
| 560 |
+
for g, methods in method_groups.items()
|
| 561 |
+
for m in methods
|
| 562 |
+
if not constraints or m in active_methods
|
| 563 |
+
]
|
| 564 |
+
if not method_choices:
|
| 565 |
+
st.warning("No active methods. Enable at least one method in the **Method Constraints** tab.")
|
| 566 |
+
return
|
| 567 |
method_lookup = {label: label.split(" | ", 1)[1] for label in method_choices}
|
| 568 |
selected_label = st.selectbox("Select a method:", method_choices, key="crra-select")
|
| 569 |
|
|
|
|
| 572 |
for r, conf in sliders.items():
|
| 573 |
st.session_state.costs[m][r] = 0.0 if (m, r) in secondary_resources else conf["median"]
|
| 574 |
for prefix in ["slider", "manual", "toggle"]:
|
| 575 |
+
st.session_state.pop(f"{prefix}_{m}_{r}".replace(" ", "_"), None)
|
| 576 |
for m, sliders in custom_sliders_by_method.items():
|
| 577 |
for r, conf in sliders.items():
|
| 578 |
st.session_state.costs.setdefault(m, {})[r] = (
|
| 579 |
0.0 if is_custom_secondary(m, r, custom_resource_to_sub_group) else conf["median"]
|
| 580 |
)
|
| 581 |
for prefix in ["slider", "manual", "toggle"]:
|
| 582 |
+
st.session_state.pop(f"{prefix}_{m}_{r}".replace(" ", "_"), None)
|
| 583 |
st.success("All methods reset to default values.")
|
| 584 |
st.rerun()
|
| 585 |
|