#!/usr/bin/env python3 """ Automated probes for Trajectories tab diagnostics. This script runs several simulated scenarios by monkeypatching explorer.load_positions, explorer.load_party_map and explorer.select_trajectory_plot_data to reproduce common failure modes that lead to "no plot at all" and prints the module-level diagnostics. Run: python scripts/diagnose_trajectories_cli.py """ import os import importlib import traceback import sys def run(): os.environ.setdefault("EXPLORER_DEBUG_TRAJECTORIES", "1") # Ensure project root is on sys.path so 'import explorer' finds the module root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) if root not in sys.path: sys.path.insert(0, root) # Import explorer fresh so env var reads take effect import explorer def run_scenario( name, load_positions_ret=None, load_party_map_ret=None, select_helper_behavior=None, ): print("\n" + "=" * 80) print("SCENARIO:", name) # Backup originals orig_load_positions = getattr(explorer, "load_positions", None) orig_load_party_map = getattr(explorer, "load_party_map", None) orig_select_helper = getattr(explorer, "select_trajectory_plot_data", None) if load_positions_ret is not None: explorer.load_positions = lambda db, ws: load_positions_ret if load_party_map_ret is not None: explorer.load_party_map = lambda db: load_party_map_ret if select_helper_behavior == "raise": def raising(*args, **kwargs): raise ValueError("simulated crash from select_trajectory_plot_data") explorer.select_trajectory_plot_data = raising elif select_helper_behavior == "zero_traces": class DummyFig: def __init__(self): self.data = [] def zero(*args, **kwargs): return DummyFig(), 0, None explorer.select_trajectory_plot_data = zero try: # Call the UI function; it's import-safe and uses a dummy st when streamlit is absent explorer.build_trajectories_tab(db_path="dummy", window_size=1) except Exception as e: print("build_trajectories_tab RAISED:", type(e), e) print(traceback.format_exc()) finally: diag = getattr(explorer, "_last_trajectories_diagnostics", None) print("module _last_trajectories_diagnostics:", diag) sh = None if hasattr(explorer, "select_trajectory_plot_data"): sh = getattr( explorer.select_trajectory_plot_data, "_last_diagnostics", None ) print("select_helper _last_diagnostics:", sh) # restore if orig_load_positions is not None: explorer.load_positions = orig_load_positions if orig_load_party_map is not None: explorer.load_party_map = orig_load_party_map if orig_select_helper is not None: explorer.select_trajectory_plot_data = orig_select_helper # Scenario 1: load_positions returns empty run_scenario( "load_positions_empty", load_positions_ret=({}, None), load_party_map_ret={} ) # Scenario 2: positions present but MP coords malformed -> mp_positions empty positions_malformed = {"W1": {"mp1": ("bad", "bad")}} run_scenario( "mp_positions_malformed", load_positions_ret=(positions_malformed, {}), load_party_map_ret={}, ) # Scenario 3: select_trajectory_plot_data raises an exception positions_valid = {"W1": {"mp1": (0.1, 0.2)}} run_scenario( "select_helper_raise", load_positions_ret=(positions_valid, {}), load_party_map_ret={}, select_helper_behavior="raise", ) # Scenario 4: helper returns a fig with zero traces run_scenario( "helper_zero_traces", load_positions_ret=(positions_valid, {}), load_party_map_ret={}, select_helper_behavior="zero_traces", ) if __name__ == "__main__": run()