refactor: use svd_labels module for fallback labels in axis_classifier (Task 3)
This commit is contained in:
+87
-54
@@ -13,6 +13,8 @@ import numpy as np
|
||||
import re
|
||||
import json
|
||||
|
||||
from analysis.svd_labels import get_svd_label
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
# Module-level caches — loaded once per process lifetime.
|
||||
@@ -23,15 +25,15 @@ _coalition_cache: Optional[Dict[str, set]] = None
|
||||
_THRESHOLD = 0.65
|
||||
|
||||
_LABELS = {
|
||||
"lr": "Links\u2013Rechts",
|
||||
"co": "Coalitie\u2013Oppositie",
|
||||
"pc": "Conservatief\u2013Progressief",
|
||||
# When we have no interpretable classifier signal, fall back to numeric SVD
|
||||
# component names (As 1 / As 2) rather than the vague "Stempatroon As N".
|
||||
# The UI will still add directional annotations (▲/▼) when rendering the
|
||||
# vertical axis to make polarity unambiguous.
|
||||
"fallback_x": "As 1",
|
||||
"fallback_y": "As 2",
|
||||
"lr": "Verzorgingsstaat–Marktwerking",
|
||||
"eu": "EU-integratie–Nationalisme",
|
||||
"pi": "Populistisch–Institutioneel",
|
||||
"co": "Coalitie–Oppositie",
|
||||
"pc": "Conservatief–Progressief",
|
||||
# When we have no interpretable classifier signal, fall back to the known
|
||||
# SVD component meanings rather than generic "As N" labels.
|
||||
"fallback_x": get_svd_label(1),
|
||||
"fallback_y": get_svd_label(2),
|
||||
}
|
||||
|
||||
|
||||
@@ -39,11 +41,29 @@ _LABELS = {
|
||||
# Remove duplicate lower definition (keep the one at the top)
|
||||
|
||||
|
||||
def display_label_for_modal(modal_label: Optional[str], axis: str) -> str:
|
||||
"""Return a user-facing axis label for a modal/internal label.
|
||||
|
||||
Keeps existing behavior: map numeric fallback names 'As 1' / 'Stempatroon As 1'
|
||||
to the conventional semantic defaults used in the UI. Any other label is
|
||||
returned unchanged; None is treated as the semantic fallback for the axis.
|
||||
"""
|
||||
if modal_label is None:
|
||||
return "Links\u2013Rechts" if axis == "x" else "Progressief\u2013Conservatief"
|
||||
if axis == "x" and modal_label in ("As 1", "Stempatroon As 1"):
|
||||
return "Links\u2013Rechts"
|
||||
if axis == "y" and modal_label in ("As 2", "Stempatroon As 2"):
|
||||
return "Progressief\u2013Conservatief"
|
||||
return modal_label
|
||||
|
||||
|
||||
_INTERPRETATION_TEMPLATES = {
|
||||
"lr": "De {orientation} as weerspiegelt de klassieke links-rechts tegenstelling.",
|
||||
"lr": "De {orientation} as weerspiegelt de economische tegenstelling tussen verzorgingsstaat en marktwerking.",
|
||||
"eu": "De {orientation} as weerspiegelt de tegenstelling tussen EU-integratie/internationalisme en nationalisme/soevereiniteit.",
|
||||
"pi": "De {orientation} as scheidt populistisch-nationalistische partijen van het institutioneel-parlementaire establishment.",
|
||||
"co": (
|
||||
"De {orientation} as weerspiegelt stemgedrag van coalitie- versus "
|
||||
"oppositiepartijen (r={r:.2f}). Links-rechts is minder dominant dit jaar."
|
||||
"oppositiepartijen (r={r:.2f}). Ideologische tegenstellingen zijn minder dominant dit jaar."
|
||||
),
|
||||
"pc": "De {orientation} as weerspiegelt de progressief-conservatieve tegenstelling.",
|
||||
"fallback": (
|
||||
@@ -55,8 +75,10 @@ _INTERPRETATION_TEMPLATES = {
|
||||
# Maps motion-path keyword labels to _INTERPRETATION_TEMPLATES keys.
|
||||
# Labels not present here fall back to "fallback".
|
||||
_MOTION_LABEL_TEMPLATE_KEY: Dict[str, str] = {
|
||||
"Links\u2013Rechts": "lr",
|
||||
"Progressief\u2013Conservatief": "pc",
|
||||
"Verzorgingsstaat–Marktwerking": "lr",
|
||||
"EU-integratie–Nationalisme": "eu",
|
||||
"Populistisch–Institutioneel": "pi",
|
||||
"Progressief–Conservatief": "pc",
|
||||
}
|
||||
|
||||
|
||||
@@ -64,8 +86,8 @@ _MOTION_LABEL_TEMPLATE_KEY: Dict[str, str] = {
|
||||
_KEYWORD_THRESHOLD = 0.4
|
||||
|
||||
_KEYWORDS: Dict[str, List[str]] = {
|
||||
"Links\u2013Rechts": [
|
||||
# economic
|
||||
"Verzorgingsstaat–Marktwerking": [
|
||||
# economic / welfare state
|
||||
"belasting",
|
||||
"uitkering",
|
||||
"bijstand",
|
||||
@@ -78,18 +100,57 @@ _KEYWORDS: Dict[str, List[str]] = {
|
||||
"pensioen",
|
||||
"aow",
|
||||
"zorg",
|
||||
# immigration
|
||||
"asiel",
|
||||
"asielaanvraag",
|
||||
"migratie",
|
||||
"vreemdeling",
|
||||
"vluchtelingen",
|
||||
"terugkeer",
|
||||
"grenzen",
|
||||
"opvang",
|
||||
"statushouder",
|
||||
"huur",
|
||||
"woning",
|
||||
"sociaal",
|
||||
"werkloos",
|
||||
"ww",
|
||||
"arbeidsongeschik",
|
||||
"wao",
|
||||
"gemeentefonds",
|
||||
],
|
||||
"Progressief\u2013Conservatief": [
|
||||
"EU-integratie–Nationalisme": [
|
||||
# EU and international cooperation
|
||||
"europees",
|
||||
"europese",
|
||||
" eu ",
|
||||
"eu-",
|
||||
"verdrag",
|
||||
"intergouvernementeel",
|
||||
"samenwerking",
|
||||
"internationaal",
|
||||
"navo",
|
||||
"nato",
|
||||
" vn ",
|
||||
"vn-",
|
||||
"sancties",
|
||||
"israël",
|
||||
"vluchteling",
|
||||
"asiel",
|
||||
"soevereiniteit",
|
||||
"nationaal",
|
||||
],
|
||||
"Populistisch–Institutioneel": [
|
||||
# Populist/nationalist themes
|
||||
"terugsturen",
|
||||
"syrië",
|
||||
"syrier",
|
||||
"grenzen dicht",
|
||||
"remigratie",
|
||||
"eigen volk",
|
||||
"nederland eerst",
|
||||
"corona",
|
||||
"vaccin",
|
||||
"ivermectine",
|
||||
"hydroxychloroquine",
|
||||
"complot",
|
||||
"deep state",
|
||||
"establishment",
|
||||
"elite",
|
||||
"herstelbetaling",
|
||||
"excuses",
|
||||
],
|
||||
"Progressief–Conservatief": [
|
||||
# environment
|
||||
"klimaat",
|
||||
"stikstof",
|
||||
@@ -109,16 +170,6 @@ _KEYWORDS: Dict[str, List[str]] = {
|
||||
"religie",
|
||||
"geloof",
|
||||
],
|
||||
"Nationaal\u2013Internationaal": [
|
||||
"navo",
|
||||
"nato",
|
||||
"europees",
|
||||
"europese",
|
||||
" eu ",
|
||||
"verdrag",
|
||||
" vn ",
|
||||
"internationaal",
|
||||
],
|
||||
}
|
||||
|
||||
# Pre-compiled regexes for keyword matching. We escape keywords but do NOT add
|
||||
@@ -454,24 +505,6 @@ def classify_axes(
|
||||
if not ideology and not motion_path_available:
|
||||
return axes
|
||||
|
||||
|
||||
def display_label_for_modal(modal_label: Optional[str], axis: str) -> str:
|
||||
"""Return a user-facing axis label for a modal/internal label.
|
||||
|
||||
Keeps existing behavior: map numeric fallback names 'As 1' / 'Stempatroon As 1'
|
||||
to the conventional semantic defaults used in the UI. Any other label is
|
||||
returned unchanged; None is treated as the semantic fallback for the axis.
|
||||
"""
|
||||
if modal_label is None:
|
||||
return "Links\u2013Rechts" if axis == "x" else "Conservatief\u2013Progressief"
|
||||
if axis == "x" and modal_label in ("As 1", "Stempatroon As 1"):
|
||||
return "Links\u2013Rechts"
|
||||
if axis == "y" and modal_label in ("As 2", "Stempatroon As 2"):
|
||||
return "Conservatief\u2013Progressief"
|
||||
return modal_label
|
||||
|
||||
# duplicate early-exit guard removed here
|
||||
|
||||
x_quality: Dict[str, float] = {}
|
||||
y_quality: Dict[str, float] = {}
|
||||
x_interpretation: Dict[str, str] = {}
|
||||
|
||||
Reference in New Issue
Block a user