You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4.6 KiB
4.6 KiB
SVD Axis Labels: Enforce Canonical Left/Right Orientation
Problem
SVD axis labels do not consistently reflect the repository's political convention: right-wing parties (PVV, FVD, JA21, SGP) must appear on the RIGHT side of all axes in visualizations. Current code uses inconsistent inline party sets across files (svd_labels.py has 9 right parties, political_axis.py has 6), and no automated validation exists to enforce the convention.
Goals
- Guarantee that canonical right-wing parties (PVV, FVD, JA21, SGP) appear on the RIGHT side of all SVD axes.
- Centralize canonical party sets in a single source of truth.
- Automatically flip axis orientation when canonical parties appear on the wrong side.
- Add unit tests and CI validation to prevent regressions.
- Maintain backward compatibility for existing callers.
Architecture
New Module: analysis/config.py
"""Canonical political party sets for axis orientation validation."""
CANONICAL_RIGHT = frozenset({"PVV", "FVD", "JA21", "SGP"})
CANONICAL_LEFT = frozenset({
"SP", "PvdA", "GL", "GroenLinks", "GroenLinks-PvdA",
"DENK", "PvdD", "Volt"
})
Updated Module: analysis/svd_labels.py
- Import canonical sets from
analysis.config. - Replace inline
RIGHT_PARTIES/LEFT_PARTIESwith config values. - Export backward-compat aliases:
from analysis.config import CANONICAL_RIGHT, CANONICAL_LEFT RIGHT_PARTIES = CANONICAL_RIGHT LEFT_PARTIES = CANONICAL_LEFT - Update
compute_flip_direction()to useCANONICAL_RIGHTfor flip decisions.
Data Flow
- Compute raw component scores/centroids (existing logic).
- Project canonical right party vectors onto the component.
- Determine where canonical right parties lie along the component axis.
- If majority of
CANONICAL_RIGHTitems are on the left side, setflip = True. - When
flipis True, swap/negate the axis and flip label semantics before returning to callers. - Numerical PCs remain intact; only orientation + labels change at presentation boundary.
Error Handling & Fallbacks
- No canonical parties present: Log warning, fall back to existing behavior (no flip), optionally surface UI notice.
- Ambiguous placement: Use majority rule with deterministic tie-breaking (tie → do not flip, log warning).
- Backward compatibility: Preserve public functions (
get_svd_label,get_fallback_labels,compute_flip_direction); only orientation may flip.
Testing Strategy
Unit Tests (tests/test_svd_labels.py)
- Synthetic flip test: Create synthetic vectors where canonical right parties have negative component values; assert
compute_flip_directionreturnsTrueand labels map correctly. - Synthetic no-flip test: Canonical right parties on positive side; assert
compute_flip_directionreturnsFalse. - Real window test: Load a representative window and assert every item from
CANONICAL_RIGHTappears on the right side after flip logic. - Backward compat test: Existing tests in
test_svd_labels.pycontinue to pass after import swap.
CI Validation
- Add pytest test group enforcing the rule:
pytest -q tests/test_svd_labels.py::test_canonical_right_on_right - Test loads at least one representative window and asserts PVV/FVD/JA21/SGP appear on the right side of the principal political axis.
- Prevents regressions in PR pipeline.
Migration Plan
- Create
analysis/config.pywith canonical sets. - Update
analysis/svd_labels.pyimports and export aliases. - Update
compute_flip_directionto use canonical sets. - Add/update unit tests in
tests/test_svd_labels.py. - Run full test suite to verify backward compatibility.
- Commit changes locally (no push until user approves).
Out of Scope (Follow-up)
analysis/political_axis.pycurrently uses different party sets for PCA centroid orientation. Recommended follow-up: align withconfig.pyin separate PR.- UI notice for missing canonical parties (non-blocking enhancement).
Success Criteria
CANONICAL_RIGHTandCANONICAL_LEFTdefined inanalysis/config.py.svd_labels.pyimports from config; exports aliases for backward compat.- All existing tests pass after changes.
- New test
test_canonical_right_on_rightpasses. - Running
pytest tests/test_svd_labels.py -qshows no regressions. - Right-wing parties (PVV, FVD, JA21, SGP) consistently appear on the RIGHT side of all axes in visualizations.
Related Files
analysis/config.py(new)analysis/svd_labels.py(update)tests/test_svd_labels.py(update)docs/solutions/best-practices/svd-labels-voting-patterns-not-semantics.md(existing convention doc)AGENTS.md(convention reference)