EmbodiedCity-Leaderboard / src /radar_plotter.py
serendipityAc2Win's picture
Deploy EmbodiedCity leaderboard
c162d1f verified
Raw
History Blame Contribute Delete
4.26 kB
from __future__ import annotations
from typing import List
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib.lines import Line2D
class RadarPlotter:
def __init__(self, data_loader):
self.data_loader = data_loader
self.dimension_metrics = list(data_loader.dimension_metrics)
self.dimension_labels = list(data_loader.dimension_display_labels)
self.color_list = [
"#1f77b4",
"#ff7f0e",
"#2ca02c",
"#d62728",
"#9467bd",
"#8c564b",
"#e377c2",
"#7f7f7f",
"#bcbd22",
"#17becf",
]
def create_radar_chart(self, models_df: pd.DataFrame) -> plt.Figure:
if models_df.empty or not self.dimension_metrics:
fig, ax = plt.subplots(figsize=(8, 6))
ax.text(0.5, 0.5, "No dimension metrics available for radar chart", ha="center", va="center", fontsize=14)
ax.axis("off")
return fig
plt.rcParams["font.family"] = "sans-serif"
plt.rcParams["font.sans-serif"] = ["Arial", "Microsoft YaHei", "SimHei", "DejaVu Sans"]
plt.rcParams["axes.unicode_minus"] = False
labels = self.dimension_labels
angles = np.linspace(0, 2 * np.pi, len(labels), endpoint=False).tolist()
angles += angles[:1]
fig = plt.figure(figsize=(13.5, 8.5))
grid = fig.add_gridspec(1, 2, width_ratios=[3.2, 1.35], wspace=0.02)
ax = fig.add_subplot(grid[0, 0], polar=True)
ax_legend = fig.add_subplot(grid[0, 1])
ax_legend.axis("off")
ax.set_theta_offset(np.pi / 2)
ax.set_theta_direction(-1)
ax.set_ylim(0, 105)
ax.set_xticks(angles[:-1])
ax.set_xticklabels(labels, fontsize=11, fontweight="bold")
ax.set_yticks([20, 40, 60, 80, 100])
ax.set_yticklabels(["20", "40", "60", "80", "100"], color="#666666")
ax.yaxis.grid(True, color="#D0D8E8", linewidth=0.8)
ax.xaxis.grid(True, color="#D0D8E8", linewidth=0.8)
ax.fill(np.linspace(0, 2 * np.pi, 400), [105] * 400, color="#EAF1FA", alpha=0.5)
model_scores = []
for _, row in models_df.iterrows():
values = [float(row.get(metric, 0) or 0) for metric in self.dimension_metrics]
valid_values = [value for value in values if value is not None]
avg_score = sum(valid_values) / len(valid_values) if valid_values else 0
model_scores.append((row, avg_score))
model_scores.sort(key=lambda item: item[1])
legend_elements = []
for index, (row, _) in enumerate(model_scores):
values = [float(row.get(metric, 0) or 0) for metric in self.dimension_metrics]
values += values[:1]
color = self.color_list[index % len(self.color_list)]
ax.plot(angles, values, color=color, linewidth=2.0, label=row["Model"])
ax.fill(angles, values, color=color, alpha=0.06)
ax.scatter(angles[:-1], values[:-1], color=color, s=36, edgecolors="white", linewidths=0.5)
legend_elements.append(
Line2D(
[0],
[0],
color=color,
linestyle="-",
marker="o",
markersize=6,
linewidth=2.0,
markerfacecolor=color,
markeredgecolor="white",
markeredgewidth=0.5,
label=row["Model"],
)
)
if legend_elements:
ax_legend.legend(
handles=legend_elements,
loc="center left",
frameon=True,
fontsize=9,
fancybox=True,
shadow=False,
edgecolor="#d9d9d9",
facecolor="white",
borderpad=0.8,
labelspacing=0.55,
handlelength=2.0,
handletextpad=0.7,
)
ax.set_title("Dimension Radar Chart", fontsize=18, fontweight="bold", pad=26)
fig.subplots_adjust(left=0.05, right=0.97, top=0.92, bottom=0.06)
return fig