feat: add axis swap — left-right goes on horizontal axis when detected

main
Sven Geboers 1 month ago
parent 95c5ab9302
commit 74b3f10d07
  1. 43
      explorer.py
  2. 70
      tests/test_political_compass.py

@ -170,6 +170,46 @@ def get_uniform_dim_windows(db_path: str) -> List[str]:
con.close()
def _should_swap_axes(axis_def: dict) -> bool:
"""Return True if the Y axis is 'Links–Rechts' and the X axis is not.
When true, caller should swap x/y positions and metadata so left-right
is conventionally on the horizontal axis.
"""
lr = "Links\u2013Rechts"
return axis_def.get("y_label") == lr and axis_def.get("x_label") != lr
def _swap_axes(
positions_by_window: dict,
axis_def: dict,
) -> tuple:
"""Swap x and y in all positions and axis metadata.
Pure function returns (new_positions_by_window, new_axis_def).
"""
new_positions: dict = {}
for wid, pos_dict in positions_by_window.items():
new_positions[wid] = {ent: (y, x) for ent, (x, y) in pos_dict.items()}
new_ax = dict(axis_def)
# Swap paired scalar keys
new_ax["x_label"] = axis_def.get("y_label")
new_ax["y_label"] = axis_def.get("x_label")
# Swap paired dict keys
for x_key, y_key in [
("x_quality", "y_quality"),
("x_interpretation", "y_interpretation"),
("x_top_motions", "y_top_motions"),
("x_label_confidence", "y_label_confidence"),
]:
new_ax[x_key] = axis_def.get(y_key)
new_ax[y_key] = axis_def.get(x_key)
return new_positions, new_ax
@st.cache_data(show_spinner="2D posities berekenen (kan even duren)…")
def load_positions(
db_path: str, window_size: str = "quarterly"
@ -210,6 +250,9 @@ def load_positions(
"classify_axes failed; using generic axis labels"
)
if _should_swap_axes(axis_def):
positions_by_window, axis_def = _swap_axes(positions_by_window, axis_def)
# Filter displayed windows by window_size AFTER PCA computation.
if window_size == "annual":
annual_keys = set(w for w in all_available if "-Q" not in w)

@ -111,6 +111,21 @@ except Exception:
_go.Figure = lambda *a, **kw: None
sys.modules["plotly.graph_objects"] = _go
# Provide a minimal streamlit stub so explorer imports succeed in the test env
try:
import streamlit as _st # noqa: F401
except Exception:
_st_stub = types.ModuleType("streamlit")
_st_stub.cache_data = lambda **kw: lambda f: f
_st_stub.plotly_chart = lambda *a, **kw: None
_st_stub.markdown = lambda *a, **kw: None
_st_stub.caption = lambda *a, **kw: None
_st_stub.error = lambda *a, **kw: None
_st_stub.warning = lambda *a, **kw: None
_st_stub.info = lambda *a, **kw: None
_st_stub.write = lambda *a, **kw: None
sys.modules["streamlit"] = _st_stub
import pytest
@ -654,3 +669,58 @@ def test_classify_from_titles_low_confidence():
label, confidence = _classify_from_titles(titles)
assert label is None
assert confidence < 0.4
def test_axis_swap_when_y_is_left_right():
"""When y_label is 'Links–Rechts' and x_label is not, positions must be swapped."""
from explorer import _swap_axes
positions_by_window = {
"2023": {
"VVD": (0.5, 0.8),
"PvdA": (-0.3, -0.6),
}
}
axis_def = {
"x_label": "Progressief\u2013Conservatief",
"y_label": "Links\u2013Rechts",
"x_quality": {"2023": 0.7},
"y_quality": {"2023": 0.8},
"x_interpretation": {"2023": "prog interpretation"},
"y_interpretation": {"2023": "lr interpretation"},
"x_top_motions": {"2023": {"+": [], "-": []}},
"y_top_motions": {"2023": {"+": [], "-": []}},
"x_label_confidence": {"2023": 0.5},
"y_label_confidence": {"2023": 0.7},
}
new_pos, new_ax = _swap_axes(positions_by_window, axis_def)
# Positions swapped: (x, y) → (y, x)
assert new_pos["2023"]["VVD"] == (0.8, 0.5)
assert new_pos["2023"]["PvdA"] == (-0.6, -0.3)
# Labels swapped
assert new_ax["x_label"] == "Links\u2013Rechts"
assert new_ax["y_label"] == "Progressief\u2013Conservatief"
# Quality swapped
assert new_ax["x_quality"] == {"2023": 0.8}
assert new_ax["y_quality"] == {"2023": 0.7}
def test_axis_swap_not_applied_when_x_is_left_right():
"""When x_label is already 'Links–Rechts', no swap should occur."""
from explorer import _should_swap_axes
axis_def = {
"x_label": "Links\u2013Rechts",
"y_label": "Progressief\u2013Conservatief",
}
assert _should_swap_axes(axis_def) is False
axis_def2 = {
"x_label": "Links\u2013Rechts",
"y_label": "Links\u2013Rechts", # both LR — no swap
}
assert _should_swap_axes(axis_def2) is False

Loading…
Cancel
Save