From 0d17c6364a2b077e7a1b1738b855827c73c0c9c8 Mon Sep 17 00:00:00 2001 From: Sven Geboers Date: Thu, 16 Apr 2026 22:20:31 +0200 Subject: [PATCH] fix: use Procrustes-aligned scores for all 10 SVD components (consistent with compass) --- explorer.py | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/explorer.py b/explorer.py index 01f0dbf..30ef6f3 100644 --- a/explorer.py +++ b/explorer.py @@ -2670,22 +2670,16 @@ def build_svd_components_tab(db_path: str) -> None: if score_list } - # Extract 1D scores for this component. - # Components 1 and 2 are literally the x and y axes of the compass (Procrustes-aligned - # PCA via compute_2d_axes). Use _get_aligned_party_coords so the numbers are identical - # to what the compass shows. Components 3-10 fall back to compute_nd_axes scores. + # Extract 1D scores for this component using Procrustes-aligned PCA scores. + # All 10 components use _get_aligned_party_scores (compute_nd_axes with annual-only + # windows). This is mathematically identical to the compass x/y positions for + # components 1 and 2, and consistently uses the same aligned data for 3-10. party_1d_coords: dict = {} - if comp_sel in (1, 2): - coord_idx = 0 if comp_sel == 1 else 1 - aligned_2d = _get_aligned_party_coords(svd_window) - for party, xy in aligned_2d.items(): - party_1d_coords[party] = (float(xy[coord_idx]),) - else: - aligned_all_scores = _get_aligned_party_scores(svd_window) - for party, all_scores in aligned_all_scores.items(): - idx = comp_sel - 1 # 0-indexed - if idx < len(all_scores): - party_1d_coords[party] = (float(all_scores[idx]),) + aligned_all_scores = _get_aligned_party_scores(svd_window) + for party, all_scores in aligned_all_scores.items(): + idx = comp_sel - 1 # 0-indexed + if idx < len(all_scores): + party_1d_coords[party] = (float(all_scores[idx]),) # Auto-compute flip directions for ALL components 1-10 based on aligned party centroids. # Since we now use aligned PCA scores for all components, compute flip directly from