""" Ranking Table Component Visualization component for model ranking based on robustness metrics. Displays rankings sorted by adversarial robustness and vulnerability index. """ import logging from typing import Any, List, Optional from dashboard.schemas import BenchmarkComparisonData, BenchmarkModelResult from dashboard.utils import format_score, log_dashboard_event logger = logging.getLogger(__name__) # Table headers for ranking display RANKING_HEADERS = [ "Rank", "Model", "R_base", "R_adv", "ΔR", "RSI", "VI", "Samples", ] def create_ranking_table( comparison: Optional[BenchmarkComparisonData], ) -> List[List[str]]: """ Create ranking table from benchmark comparison data. Ranking rules: - Primary: Sort by R_adv (descending) - Secondary: Sort by VI (ascending - lower is better) Args: comparison: BenchmarkComparisonData object Returns: Table data as list of rows """ if comparison is None or not comparison.model_results: return [create_empty_row()] log_dashboard_event( "DASHBOARD_VIEW_RANKING_TABLE", benchmark_id=comparison.benchmark_id, ) return update_ranking_table(comparison) def update_ranking_table( comparison: BenchmarkComparisonData, ) -> List[List[str]]: """ Update ranking table with benchmark comparison data. Args: comparison: BenchmarkComparisonData object Returns: Table data as list of rows """ if not comparison.model_results: return [create_empty_row()] # Results are already sorted by the schema # Primary: R_adv descending # Secondary: VI ascending table_data = [] for result in comparison.model_results: row = [ str(result.rank), result.model_name, format_score(result.baseline_robustness, 4), format_score(result.adversarial_robustness, 4), format_score(result.delta_robustness, 4), format_score(result.rsi, 4), format_score(result.vulnerability_index, 4), str(result.sample_count), ] table_data.append(row) return table_data def create_ranking_table_from_results( results: List[BenchmarkModelResult], ) -> List[List[str]]: """ Create ranking table from list of model results. Args: results: List of BenchmarkModelResult objects Returns: Table data as list of rows """ if not results: return [create_empty_row()] # Sort by R_adv descending, then VI ascending sorted_results = sorted( results, key=lambda x: (x.adversarial_robustness, -x.vulnerability_index), reverse=True, ) # Assign ranks for i, result in enumerate(sorted_results): result.rank = i + 1 table_data = [] for result in sorted_results: row = [ str(result.rank), result.model_name, format_score(result.baseline_robustness, 4), format_score(result.adversarial_robustness, 4), format_score(result.delta_robustness, 4), format_score(result.rsi, 4), format_score(result.vulnerability_index, 4), str(result.sample_count), ] table_data.append(row) return table_data def create_empty_row() -> List[str]: """ Create empty row for table. Returns: List of default values """ return ["N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "0"] def get_ranking_headers() -> List[str]: """ Get ranking table headers. Returns: List of header strings """ return RANKING_HEADERS def format_ranking_tooltip(result: BenchmarkModelResult) -> str: """ Format ranking tooltip for a model result. Args: result: BenchmarkModelResult object Returns: Formatted tooltip string """ return ( f"{result.model_name}
" f"Rank: #{result.rank}
" f"R_base: {result.baseline_robustness:.4f}
" f"R_adv: {result.adversarial_robustness:.4f}
" f"ΔR: {result.delta_robustness:.4f}
" f"RSI: {result.rsi:.4f}
" f"VI: {result.vulnerability_index:.4f}
" f"Samples: {result.sample_count}" ) def get_rsi_interpretation(rsi: float) -> str: """ Get interpretation string for RSI value. Args: rsi: RSI value Returns: Interpretation string """ if rsi >= 0.9: return "Very Stable" elif rsi >= 0.7: return "Moderately Stable" elif rsi >= 0.5: return "Unstable" else: return "Highly Unstable" def get_vi_interpretation(vi: float) -> str: """ Get interpretation string for VI value. Args: vi: VI value Returns: Interpretation string """ if vi < 0.1: return "Highly Resilient" elif vi < 0.3: return "Moderately Resilient" elif vi < 0.5: return "Vulnerable" else: return "Highly Vulnerable" def get_delta_interpretation(delta: float) -> str: """ Get interpretation string for delta robustness value. Args: delta: Delta robustness value Returns: Interpretation string """ if delta < 0.0: return "Better Under Attack" elif delta < 0.1: return "Highly Robust" elif delta < 0.3: return "Moderately Robust" elif delta < 0.5: return "Vulnerable" else: return "Severely Vulnerable"