refactor: use svd_labels for fallback labels in explorer and axis_classifier (Task 4)
This commit is contained in:
+17
-10
@@ -13,7 +13,7 @@ import numpy as np
|
|||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from analysis.svd_labels import get_svd_label
|
from analysis.svd_labels import get_svd_label, get_fallback_labels
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -44,16 +44,21 @@ _LABELS = {
|
|||||||
def display_label_for_modal(modal_label: Optional[str], axis: str) -> str:
|
def display_label_for_modal(modal_label: Optional[str], axis: str) -> str:
|
||||||
"""Return a user-facing axis label for a modal/internal label.
|
"""Return a user-facing axis label for a modal/internal label.
|
||||||
|
|
||||||
Keeps existing behavior: map numeric fallback names 'As 1' / 'Stempatroon As 1'
|
Maps numeric fallback names 'As 1' / 'Stempatroon As 1' to the
|
||||||
to the conventional semantic defaults used in the UI. Any other label is
|
semantic labels from SVD_THEMES. Any other label is returned unchanged.
|
||||||
returned unchanged; None is treated as the semantic fallback for the axis.
|
None is treated as the semantic fallback for the axis.
|
||||||
"""
|
"""
|
||||||
if modal_label is None:
|
if modal_label is None:
|
||||||
return "Links\u2013Rechts" if axis == "x" else "Progressief\u2013Conservatief"
|
# Fallback to component 1 (x) or 2 (y)
|
||||||
|
comp = 1 if axis == "x" else 2
|
||||||
|
return get_svd_label(comp)
|
||||||
|
|
||||||
|
# Map "As 1" / "As 2" to semantic labels
|
||||||
if axis == "x" and modal_label in ("As 1", "Stempatroon As 1"):
|
if axis == "x" and modal_label in ("As 1", "Stempatroon As 1"):
|
||||||
return "Links\u2013Rechts"
|
return get_svd_label(1)
|
||||||
if axis == "y" and modal_label in ("As 2", "Stempatroon As 2"):
|
if axis == "y" and modal_label in ("As 2", "Stempatroon As 2"):
|
||||||
return "Progressief\u2013Conservatief"
|
return get_svd_label(2)
|
||||||
|
|
||||||
return modal_label
|
return modal_label
|
||||||
|
|
||||||
|
|
||||||
@@ -430,7 +435,8 @@ def _assign_label(
|
|||||||
Returns (label, interpretation_string, quality_score).
|
Returns (label, interpretation_string, quality_score).
|
||||||
"""
|
"""
|
||||||
orientation = "horizontale" if axis == "x" else "verticale"
|
orientation = "horizontale" if axis == "x" else "verticale"
|
||||||
fallback_label = _LABELS["fallback_x"] if axis == "x" else _LABELS["fallback_y"]
|
_x_fallback, _y_fallback = get_fallback_labels()
|
||||||
|
fallback_label = _x_fallback if axis == "x" else _y_fallback
|
||||||
quality = max(abs(r_lr), abs(r_co), abs(r_pc))
|
quality = max(abs(r_lr), abs(r_co), abs(r_pc))
|
||||||
|
|
||||||
if abs(r_lr) >= _THRESHOLD:
|
if abs(r_lr) >= _THRESHOLD:
|
||||||
@@ -608,13 +614,14 @@ def classify_axes(
|
|||||||
|
|
||||||
# ── Final label resolution ────────────────────────────────────────────
|
# ── Final label resolution ────────────────────────────────────────────
|
||||||
# If both motion and ideology paths produced nothing, use generic fallback.
|
# If both motion and ideology paths produced nothing, use generic fallback.
|
||||||
|
_x_fallback, _y_fallback = get_fallback_labels()
|
||||||
if x_lbl is None:
|
if x_lbl is None:
|
||||||
x_lbl = _LABELS["fallback_x"]
|
x_lbl = _x_fallback
|
||||||
x_int = _INTERPRETATION_TEMPLATES["fallback"].format(
|
x_int = _INTERPRETATION_TEMPLATES["fallback"].format(
|
||||||
orientation="horizontale"
|
orientation="horizontale"
|
||||||
)
|
)
|
||||||
if y_lbl is None:
|
if y_lbl is None:
|
||||||
y_lbl = _LABELS["fallback_y"]
|
y_lbl = _y_fallback
|
||||||
y_int = _INTERPRETATION_TEMPLATES["fallback"].format(
|
y_int = _INTERPRETATION_TEMPLATES["fallback"].format(
|
||||||
orientation="verticale"
|
orientation="verticale"
|
||||||
)
|
)
|
||||||
|
|||||||
+6
-3
@@ -1612,15 +1612,18 @@ def build_compass_tab(db_path: str, window_size: str) -> None:
|
|||||||
# Use the classifier helper to map internal/modal labels (e.g. "As 1") to
|
# Use the classifier helper to map internal/modal labels (e.g. "As 1") to
|
||||||
# user-facing labels. Import at function-time to avoid module import cycles
|
# user-facing labels. Import at function-time to avoid module import cycles
|
||||||
# and keep explorer lightweight. If the helper is unavailable fall back to
|
# and keep explorer lightweight. If the helper is unavailable fall back to
|
||||||
# conventional semantic defaults so the UI remains readable.
|
# labels from the unified svd_labels module.
|
||||||
try:
|
try:
|
||||||
from analysis.axis_classifier import display_label_for_modal
|
from analysis.axis_classifier import display_label_for_modal
|
||||||
|
|
||||||
_x_label = display_label_for_modal(_raw_x, "x")
|
_x_label = display_label_for_modal(_raw_x, "x")
|
||||||
_y_label = display_label_for_modal(_raw_y, "y")
|
_y_label = display_label_for_modal(_raw_y, "y")
|
||||||
except Exception:
|
except Exception:
|
||||||
_x_label = _raw_x or "EU-integratie–Nationalisme"
|
from analysis.svd_labels import get_fallback_labels
|
||||||
_y_label = _raw_y or "Populistisch–Institutioneel"
|
|
||||||
|
_x_fallback, _y_fallback = get_fallback_labels()
|
||||||
|
_x_label = _raw_x or _x_fallback
|
||||||
|
_y_label = _raw_y or _y_fallback
|
||||||
|
|
||||||
if level == "Partijen":
|
if level == "Partijen":
|
||||||
# Aggregate to party centroids
|
# Aggregate to party centroids
|
||||||
|
|||||||
@@ -4,21 +4,34 @@ from analysis import axis_classifier
|
|||||||
|
|
||||||
|
|
||||||
def test_display_label_for_modal():
|
def test_display_label_for_modal():
|
||||||
assert axis_classifier.display_label_for_modal("As 1", "x") == "Links\u2013Rechts"
|
"""Test that display_label_for_modal uses SVD_THEMES for fallback labels."""
|
||||||
assert (
|
# None should return fallback from SVD_THEMES
|
||||||
axis_classifier.display_label_for_modal("Stempatroon As 1", "x")
|
x_label = axis_classifier.display_label_for_modal(None, "x")
|
||||||
== "Links\u2013Rechts"
|
y_label = axis_classifier.display_label_for_modal(None, "y")
|
||||||
)
|
|
||||||
assert (
|
# Should return component 1 and 2 labels from SVD_THEMES
|
||||||
axis_classifier.display_label_for_modal("As 2", "y")
|
assert "EU-integratie" in x_label or "Nationalisme" in x_label
|
||||||
== "Conservatief\u2013Progressief"
|
assert "Populistisch" in y_label or "Institutioneel" in y_label
|
||||||
)
|
|
||||||
assert (
|
|
||||||
axis_classifier.display_label_for_modal("Stempatroon As 2", "y")
|
def test_display_label_for_modal_maps_as_labels():
|
||||||
== "Conservatief\u2013Progressief"
|
"""Test that 'As 1' and 'As 2' are mapped to semantic labels."""
|
||||||
)
|
x_label = axis_classifier.display_label_for_modal("As 1", "x")
|
||||||
# None maps to conventional fallback
|
y_label = axis_classifier.display_label_for_modal("As 2", "y")
|
||||||
assert axis_classifier.display_label_for_modal(None, "x") == "Links\u2013Rechts"
|
|
||||||
|
# Should return component 1 and 2 labels
|
||||||
|
assert "EU-integratie" in x_label or "Nationalisme" in x_label
|
||||||
|
assert "Populistisch" in y_label or "Institutioneel" in y_label
|
||||||
|
|
||||||
|
|
||||||
|
def test_display_label_for_modal_stempatroon():
|
||||||
|
"""Test that 'Stempatroon As N' are mapped to semantic labels."""
|
||||||
|
x_label = axis_classifier.display_label_for_modal("Stempatroon As 1", "x")
|
||||||
|
y_label = axis_classifier.display_label_for_modal("Stempatroon As 2", "y")
|
||||||
|
|
||||||
|
# Should return component 1 and 2 labels
|
||||||
|
assert "EU-integratie" in x_label or "Nationalisme" in x_label
|
||||||
|
assert "Populistisch" in y_label or "Institutioneel" in y_label
|
||||||
|
|
||||||
|
|
||||||
def test_classify_axes_modal_fallback(monkeypatch, tmp_path):
|
def test_classify_axes_modal_fallback(monkeypatch, tmp_path):
|
||||||
@@ -69,5 +82,10 @@ def test_classify_axes_modal_fallback(monkeypatch, tmp_path):
|
|||||||
if not enriched or not isinstance(enriched, dict):
|
if not enriched or not isinstance(enriched, dict):
|
||||||
pytest.skip("classify_axes returned no enrichment in this environment")
|
pytest.skip("classify_axes returned no enrichment in this environment")
|
||||||
|
|
||||||
assert enriched["x_label"] == "Links\u2013Rechts"
|
# Should now return SVD component labels instead of hardcoded values
|
||||||
assert enriched["y_label"] == "Progressief\u2013Conservatief"
|
assert (
|
||||||
|
"EU-integratie" in enriched["x_label"] or "Nationalisme" in enriched["x_label"]
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
"Populistisch" in enriched["y_label"] or "Institutioneel" in enriched["y_label"]
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user