diff --git a/explorer.py b/explorer.py index b4bf50c..056a1ae 100644 --- a/explorer.py +++ b/explorer.py @@ -1963,6 +1963,7 @@ def build_trajectories_tab(db_path: str, window_size: str) -> None: fig = go.Figure() trace_count = 0 + helper_succeeded = False # New: delegate plotting selection to helper for testability # Note: select_trajectory_plot_data returns (fig, trace_count, banner_text) try: @@ -1973,6 +1974,7 @@ def build_trajectories_tab(db_path: str, window_size: str) -> None: if fig2 is not None: fig = fig2 trace_count = trace_count2 + helper_succeeded = True if banner_text: try: st.caption(banner_text) @@ -2002,38 +2004,40 @@ def build_trajectories_tab(db_path: str, window_size: str) -> None: st.text_area("select_trajectory_plot_data traceback", tb, height=240) except Exception: pass - for party in selected_parties: - if party not in centroids: - continue - wids_sorted = sorted(centroids[party].keys()) - xs_raw = [centroids[party][w][0] for w in wids_sorted] - ys_raw = [centroids[party][w][1] for w in wids_sorted] - xs = _ema_smooth(xs_raw, smooth_alpha) - ys = _ema_smooth(ys_raw, smooth_alpha) - # Preserve raw (unsmoothed) values per-point so hover can show both raw and smoothed - custom_raw = [(float(rx), float(ry)) for rx, ry in zip(xs_raw, ys_raw)] - colour = PARTY_COLOURS.get(party, "#9E9E9E") - fig.add_trace( - go.Scatter( - x=xs, - y=ys, - mode="lines+markers", - name=party, - text=wids_sorted, # full window ID for hover - customdata=custom_raw, - line=dict(color=colour, shape="spline", smoothing=1.3), - marker=dict(color=colour, size=8), - hovertemplate=( - f"{party}
" - "venster: %{text}
" - "x (smoothed): %{x:.3f}
" - "x (raw): %{customdata[0]:.3f}
" - "y (smoothed): %{y:.3f}
" - "y (raw): %{customdata[1]:.3f}" - ), + print(f"[TRAJ DEBUG] helper_succeeded={helper_succeeded}") + if not helper_succeeded: + for party in selected_parties: + if party not in centroids: + continue + wids_sorted = sorted(centroids[party].keys()) + xs_raw = [centroids[party][w][0] for w in wids_sorted] + ys_raw = [centroids[party][w][1] for w in wids_sorted] + xs = _ema_smooth(xs_raw, smooth_alpha) + ys = _ema_smooth(ys_raw, smooth_alpha) + # Preserve raw (unsmoothed) values per-point so hover can show both raw and smoothed + custom_raw = [(float(rx), float(ry)) for rx, ry in zip(xs_raw, ys_raw)] + colour = PARTY_COLOURS.get(party, "#9E9E9E") + fig.add_trace( + go.Scatter( + x=xs, + y=ys, + mode="lines+markers", + name=party, + text=wids_sorted, # full window ID for hover + customdata=custom_raw, + line=dict(color=colour, shape="spline", smoothing=1.3), + marker=dict(color=colour, size=8), + hovertemplate=( + f"{party}
" + "venster: %{text}
" + "x (smoothed): %{x:.3f}
" + "x (raw): %{customdata[0]:.3f}
" + "y (smoothed): %{y:.3f}
" + "y (raw): %{customdata[1]:.3f}" + ), + ) ) - ) - trace_count += 1 + trace_count += 1 # For trajectories, the chart spans multiple windows. Use the classifier's # per-window confidences aggregated (mean) to decide whether to use the