Spaces:
Sleeping
Sleeping
[REFACTOR] tab2: extract refresh_active_methods from _sync_constraint_widgets so it can be called without visiting Tab 2
Browse files- tabs/tab2_constraints.py +45 -16
tabs/tab2_constraints.py
CHANGED
|
@@ -3,7 +3,7 @@ import streamlit as st
|
|
| 3 |
|
| 4 |
from config.config import CO2_UNIT, method_groups, method_order, method_tooltips, secondary_resources, hidden_resource_names
|
| 5 |
from utils.ui_helpers import show_bar
|
| 6 |
-
from utils.data_utils import strip_unit_suffix,
|
| 7 |
|
| 8 |
|
| 9 |
def _make_slider_cb(m):
|
|
@@ -385,30 +385,37 @@ def build_summary_df():
|
|
| 385 |
|
| 386 |
|
| 387 |
|
| 388 |
-
def
|
| 389 |
-
"""
|
| 390 |
|
| 391 |
-
|
| 392 |
-
-
|
| 393 |
-
|
| 394 |
-
|
| 395 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 396 |
|
| 397 |
Args:
|
| 398 |
-
cost_sliders_norm (dict): {method: {resource: {min, median, max}}} with
|
|
|
|
| 399 |
|
| 400 |
Returns:
|
| 401 |
-
|
| 402 |
"""
|
| 403 |
-
just_loaded = st.session_state.pop("constraints_just_loaded", False)
|
| 404 |
-
just_activated = st.session_state.pop("just_activated_methods", set())
|
| 405 |
auto_disabled = st.session_state.get("auto_disabled_methods", set())
|
|
|
|
| 406 |
|
| 407 |
for m, c in st.session_state.constraints.items():
|
| 408 |
if get_all_missing_required(m, cost_sliders_norm):
|
| 409 |
st.session_state.constraints[m]["active"] = False
|
| 410 |
-
# Keep the method in auto_disabled so
|
| 411 |
-
#
|
| 412 |
auto_disabled.add(m)
|
| 413 |
st.session_state.pop(f"toggle_{m}", None)
|
| 414 |
st.session_state.pop(f"cap_type_{m}", None)
|
|
@@ -421,6 +428,30 @@ def _sync_constraint_widgets(cost_sliders_norm):
|
|
| 421 |
auto_disabled.discard(m)
|
| 422 |
just_activated.add(m)
|
| 423 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 424 |
force = just_loaded or (m in just_activated)
|
| 425 |
if c["active"]:
|
| 426 |
cap_type = c.get("cap_type", "percent")
|
|
@@ -457,8 +488,6 @@ def _sync_constraint_widgets(cost_sliders_norm):
|
|
| 457 |
st.session_state.pop(f"slider_{m}", None)
|
| 458 |
st.session_state.pop(f"manual_{m}", None)
|
| 459 |
|
| 460 |
-
st.session_state["auto_disabled_methods"] = auto_disabled
|
| 461 |
-
|
| 462 |
|
| 463 |
def render_constraints_summary():
|
| 464 |
"""Render the summary dataframe of active methods and their caps.
|
|
|
|
| 3 |
|
| 4 |
from config.config import CO2_UNIT, method_groups, method_order, method_tooltips, secondary_resources, hidden_resource_names
|
| 5 |
from utils.ui_helpers import show_bar
|
| 6 |
+
from utils.data_utils import strip_unit_suffix, get_other_method_variants, make_variant_name, default_constraint
|
| 7 |
|
| 8 |
|
| 9 |
def _make_slider_cb(m):
|
|
|
|
| 385 |
|
| 386 |
|
| 387 |
|
| 388 |
+
def refresh_active_methods(cost_sliders_norm):
|
| 389 |
+
"""Auto-activate/deactivate methods based on real resource availability.
|
| 390 |
|
| 391 |
+
A method is auto-deactivated when it's missing a required resource, and
|
| 392 |
+
auto-reactivated (only if it was previously auto-deactivated, not
|
| 393 |
+
manually turned off by the user) once that resource becomes available
|
| 394 |
+
again.
|
| 395 |
+
|
| 396 |
+
This must run on every app render — not just when Tab 2 itself draws —
|
| 397 |
+
otherwise a user who goes straight from Tab 1 to Tab 3/4/5 without
|
| 398 |
+
visiting Tab 2 first finds every method stuck at its initial
|
| 399 |
+
"active: False" state (set once at app startup), and the optimisation
|
| 400 |
+
fails with "No active methods" despite correctly configured resources.
|
| 401 |
+
Call this from app.py's shared init in addition to Tab 2's own
|
| 402 |
+
_sync_constraint_widgets (which calls it too, for its widget-key sync).
|
| 403 |
|
| 404 |
Args:
|
| 405 |
+
cost_sliders_norm (dict): {method: {resource: {min, median, max}}} with
|
| 406 |
+
unit suffixes stripped.
|
| 407 |
|
| 408 |
Returns:
|
| 409 |
+
set[str]: method names that were just (re)activated by this call.
|
| 410 |
"""
|
|
|
|
|
|
|
| 411 |
auto_disabled = st.session_state.get("auto_disabled_methods", set())
|
| 412 |
+
just_activated = set()
|
| 413 |
|
| 414 |
for m, c in st.session_state.constraints.items():
|
| 415 |
if get_all_missing_required(m, cost_sliders_norm):
|
| 416 |
st.session_state.constraints[m]["active"] = False
|
| 417 |
+
# Keep the method in auto_disabled so it gets re-enabled (and
|
| 418 |
+
# fires just_activated) once the resource is added.
|
| 419 |
auto_disabled.add(m)
|
| 420 |
st.session_state.pop(f"toggle_{m}", None)
|
| 421 |
st.session_state.pop(f"cap_type_{m}", None)
|
|
|
|
| 428 |
auto_disabled.discard(m)
|
| 429 |
just_activated.add(m)
|
| 430 |
|
| 431 |
+
st.session_state["auto_disabled_methods"] = auto_disabled
|
| 432 |
+
return just_activated
|
| 433 |
+
|
| 434 |
+
|
| 435 |
+
def _sync_constraint_widgets(cost_sliders_norm):
|
| 436 |
+
"""Drive all constraint widget keys from the constraint dict before any widget is drawn.
|
| 437 |
+
|
| 438 |
+
Two modes:
|
| 439 |
+
- force mode: after a file/scenario load (constraints_just_loaded flag) or for
|
| 440 |
+
freshly activated methods (just_activated_methods). All keys are set
|
| 441 |
+
unconditionally from the constraint.
|
| 442 |
+
- normal mode: setdefault only; never overrides a value the user already set.
|
| 443 |
+
|
| 444 |
+
Args:
|
| 445 |
+
cost_sliders_norm (dict): {method: {resource: {min, median, max}}} with unit suffixes stripped.
|
| 446 |
+
|
| 447 |
+
Returns:
|
| 448 |
+
None
|
| 449 |
+
"""
|
| 450 |
+
just_loaded = st.session_state.pop("constraints_just_loaded", False)
|
| 451 |
+
just_activated = st.session_state.pop("just_activated_methods", set())
|
| 452 |
+
just_activated |= refresh_active_methods(cost_sliders_norm)
|
| 453 |
+
|
| 454 |
+
for m, c in st.session_state.constraints.items():
|
| 455 |
force = just_loaded or (m in just_activated)
|
| 456 |
if c["active"]:
|
| 457 |
cap_type = c.get("cap_type", "percent")
|
|
|
|
| 488 |
st.session_state.pop(f"slider_{m}", None)
|
| 489 |
st.session_state.pop(f"manual_{m}", None)
|
| 490 |
|
|
|
|
|
|
|
| 491 |
|
| 492 |
def render_constraints_summary():
|
| 493 |
"""Render the summary dataframe of active methods and their caps.
|