fix(trajectory): improve fallback handling and diagnostics when trace_count is 0
This commit is contained in:
+56
-29
@@ -1777,6 +1777,11 @@ def build_trajectories_tab(db_path: str, window_size: str) -> None:
|
|||||||
# If no party-level centroids were computed, fall back to per-MP trajectories
|
# If no party-level centroids were computed, fall back to per-MP trajectories
|
||||||
# so the user still sees a plot even when the party_map is missing or empty.
|
# so the user still sees a plot even when the party_map is missing or empty.
|
||||||
if not centroids:
|
if not centroids:
|
||||||
|
# Fallback: plot individual MP trajectories
|
||||||
|
st.info(
|
||||||
|
"Partijcentroiden niet beschikbaar — tonen individuele MP-trajecten als fallback."
|
||||||
|
)
|
||||||
|
|
||||||
# Build per-MP time series from positions_by_window
|
# Build per-MP time series from positions_by_window
|
||||||
mp_positions: Dict[str, Dict[str, Tuple[float, float]]] = {}
|
mp_positions: Dict[str, Dict[str, Tuple[float, float]]] = {}
|
||||||
for wid in windows:
|
for wid in windows:
|
||||||
@@ -1790,20 +1795,22 @@ def build_trajectories_tab(db_path: str, window_size: str) -> None:
|
|||||||
continue
|
continue
|
||||||
mp_positions.setdefault(mp_name, {})[wid] = (x, y)
|
mp_positions.setdefault(mp_name, {})[wid] = (x, y)
|
||||||
|
|
||||||
|
# Filter to MPs with at least 2 windows and not all NaN
|
||||||
|
mp_positions = {
|
||||||
|
mp: pos
|
||||||
|
for mp, pos in mp_positions.items()
|
||||||
|
if len(pos) >= 2
|
||||||
|
and not all(np.isnan(x) and np.isnan(y) for x, y in pos.values())
|
||||||
|
}
|
||||||
|
|
||||||
if not mp_positions:
|
if not mp_positions:
|
||||||
try:
|
st.warning("Geen positiedata beschikbaar voor trajectplotten.")
|
||||||
_last_trajectories_diagnostics.update(
|
_last_trajectories_diagnostics.update(
|
||||||
{
|
{
|
||||||
"stage": "no_mp_positions",
|
"stage": "no_mp_positions",
|
||||||
"mp_positions_count": len(mp_positions),
|
"mp_positions_count": 0,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
st.info("Geen positiedata beschikbaar voor trajectplotten.")
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
# show diagnostics when debug enabled
|
# show diagnostics when debug enabled
|
||||||
try:
|
try:
|
||||||
if get_debug_trajectories_enabled():
|
if get_debug_trajectories_enabled():
|
||||||
@@ -1819,6 +1826,9 @@ def build_trajectories_tab(db_path: str, window_size: str) -> None:
|
|||||||
pass
|
pass
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Store for later use
|
||||||
|
st.session_state["_trajectory_mp_positions"] = mp_positions
|
||||||
|
|
||||||
mp_list = sorted(mp_positions.keys())
|
mp_list = sorted(mp_positions.keys())
|
||||||
default_mps = mp_list[:6]
|
default_mps = mp_list[:6]
|
||||||
selected_mps = st.multiselect(
|
selected_mps = st.multiselect(
|
||||||
@@ -2170,24 +2180,41 @@ def choose_trajectory_title(axis_def: dict, axis: str, threshold: float = 0.65)
|
|||||||
"sample_size": len(sample_mps),
|
"sample_size": len(sample_mps),
|
||||||
}
|
}
|
||||||
if trace_count == 0:
|
if trace_count == 0:
|
||||||
try:
|
st.info("📊 **Geen trajecten getekend**")
|
||||||
st.info(
|
|
||||||
"Geen trajecten getekend: geen geselecteerde partijen met voldoende data. Controleer de partijselectie en de 'Min. Kamerleden per partij' instelling."
|
# Show diagnostic information
|
||||||
|
with st.expander("🔍 Diagnostische informatie"):
|
||||||
|
st.write("**Data status:**")
|
||||||
|
st.write(
|
||||||
|
f"- Positie vensters: {len(positions_by_window) if positions_by_window else 0}"
|
||||||
)
|
)
|
||||||
except Exception:
|
st.write(f"- Party mappings: {len(party_map) if party_map else 0}")
|
||||||
pass
|
st.write(
|
||||||
if debug_enabled:
|
f"- Geselecteerde partijen: {len(selected_parties) if selected_parties else 0}"
|
||||||
try:
|
)
|
||||||
st.text_area(
|
|
||||||
"Trajectories diagnostics",
|
if "centroid_diagnostics" in locals():
|
||||||
json.dumps(_last_trajectories_diagnostics, default=str),
|
st.write("**Centroid berekening:**")
|
||||||
height=240,
|
st.write(
|
||||||
|
f"- Partijen met posities: {len(centroid_diagnostics.get('parties_with_positions', []))}"
|
||||||
)
|
)
|
||||||
except Exception:
|
st.write(
|
||||||
try:
|
f"- Partijen met alleen NaN: {len(centroid_diagnostics.get('parties_all_nan', []))}"
|
||||||
st.json(_last_trajectories_diagnostics)
|
)
|
||||||
except Exception:
|
|
||||||
pass
|
st.write("\n**Mogelijke oorzaken:**")
|
||||||
|
st.write("1. Geen SVD vectoren berekend voor de geselecteerde vensters")
|
||||||
|
st.write("2. MP namen in posities komen niet overeen met party_map")
|
||||||
|
st.write("3. Alle geselecteerde partijen hebben te weinig MPs (< 5)")
|
||||||
|
|
||||||
|
# Add a button to run diagnostics
|
||||||
|
if st.button("🔧 Database diagnostiek uitvoeren"):
|
||||||
|
with st.spinner("Bezig met diagnostiek..."):
|
||||||
|
# Import and run diagnostics
|
||||||
|
from scripts.diagnose_trajectories_cli import diagnose_trajectories
|
||||||
|
|
||||||
|
results = diagnose_trajectories(db_path)
|
||||||
|
st.json(results)
|
||||||
else:
|
else:
|
||||||
# DEBUG: show trace_count and figure data size before rendering
|
# DEBUG: show trace_count and figure data size before rendering
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user