sync to server
This commit is contained in:
+53
-29
@@ -481,7 +481,6 @@ def load_positions(
|
||||
"""
|
||||
from analysis.political_axis import compute_2d_axes
|
||||
|
||||
# Use only annual windows (quarterly windows are excluded by get_uniform_dim_windows).
|
||||
all_available = get_uniform_dim_windows(db_path)
|
||||
|
||||
if not all_available:
|
||||
@@ -539,6 +538,56 @@ def load_active_mps(db_path: str) -> set:
|
||||
return explorer_data.load_active_mps(db_path)
|
||||
|
||||
|
||||
def get_aligned_party_scores(
|
||||
db_path: str, window: str, active_mps: set | None = None
|
||||
) -> Dict[str, np.ndarray]:
|
||||
"""Get party scores for all N components from aligned PCA positions.
|
||||
|
||||
For current_parliament, pass active_mps to filter to only seated MPs
|
||||
(matching the compass behaviour). Historical windows include all MPs.
|
||||
|
||||
Args:
|
||||
db_path: Path to DuckDB database
|
||||
window: Window identifier (e.g. 'current_parliament', '2025')
|
||||
active_mps: Set of active MP names to filter current_parliament by.
|
||||
Required when window is 'current_parliament' to match compass.
|
||||
"""
|
||||
from analysis.political_axis import compute_nd_axes
|
||||
|
||||
annual_windows = get_uniform_dim_windows(db_path)
|
||||
scores_by_window, _ = compute_nd_axes(
|
||||
db_path, window_ids=annual_windows, n_components=10
|
||||
)
|
||||
window_scores = scores_by_window.get(window, {})
|
||||
if not window_scores:
|
||||
return {}
|
||||
|
||||
# For current_parliament, filter to active MPs (still seated) to match compass.
|
||||
# Historical windows include all MPs active at the time — no restriction needed.
|
||||
if window == "current_parliament" and active_mps is not None:
|
||||
window_scores = {mp: sc for mp, sc in window_scores.items() if mp in active_mps}
|
||||
|
||||
# Load party map to convert MP names to parties
|
||||
_party_map = load_party_map(db_path)
|
||||
|
||||
# Aggregate MP scores to party centroids per component
|
||||
n_comps = 10
|
||||
party_scores_agg: Dict[str, List[np.ndarray]] = {}
|
||||
for mp_name, scores in window_scores.items():
|
||||
party = _party_map.get(
|
||||
mp_name, _party_map.get(mp_name.split("(")[0].strip(), None)
|
||||
)
|
||||
if party:
|
||||
party_scores_agg.setdefault(party, []).append(scores[:n_comps])
|
||||
|
||||
# Compute mean scores per party for each component
|
||||
return {
|
||||
party: np.mean(np.vstack(score_list), axis=0)
|
||||
for party, score_list in party_scores_agg.items()
|
||||
if score_list
|
||||
}
|
||||
|
||||
|
||||
def compute_party_discipline(
|
||||
db_path: str,
|
||||
start_date: str,
|
||||
@@ -2640,35 +2689,10 @@ def build_svd_components_tab(db_path: str) -> None:
|
||||
# This ensures consistency between compass and SVD components tab.
|
||||
def _get_aligned_party_scores(window: str) -> Dict[str, np.ndarray]:
|
||||
"""Get party scores for all N components from aligned PCA positions."""
|
||||
from analysis.political_axis import compute_nd_axes
|
||||
|
||||
annual_windows = get_uniform_dim_windows(db_path)
|
||||
scores_by_window, _ = compute_nd_axes(
|
||||
db_path, window_ids=annual_windows, n_components=10
|
||||
active_mps = (
|
||||
load_active_mps(db_path) if window == "current_parliament" else None
|
||||
)
|
||||
window_scores = scores_by_window.get(window, {})
|
||||
if not window_scores:
|
||||
return {}
|
||||
|
||||
# Load party map to convert MP names to parties
|
||||
_party_map = load_party_map(db_path)
|
||||
|
||||
# Aggregate MP scores to party centroids per component
|
||||
n_comps = 10
|
||||
party_scores_agg: Dict[str, List[np.ndarray]] = {}
|
||||
for mp_name, scores in window_scores.items():
|
||||
party = _party_map.get(
|
||||
mp_name, _party_map.get(mp_name.split("(")[0].strip(), None)
|
||||
)
|
||||
if party:
|
||||
party_scores_agg.setdefault(party, []).append(scores[:n_comps])
|
||||
|
||||
# Compute mean scores per party for each component
|
||||
return {
|
||||
party: np.mean(np.vstack(score_list), axis=0)
|
||||
for party, score_list in party_scores_agg.items()
|
||||
if score_list
|
||||
}
|
||||
return get_aligned_party_scores(db_path, window, active_mps)
|
||||
|
||||
# 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
|
||||
|
||||
Reference in New Issue
Block a user