|
|
import matplotlib.pyplot as plt |
|
|
import pandas as pd |
|
|
|
|
|
def create_summary_page(df: pd.DataFrame, available_models: list[str]) -> plt.Figure: |
|
|
"""Create a summary page with model names and both AMD/NVIDIA test stats bars.""" |
|
|
if df.empty: |
|
|
fig, ax = plt.subplots(figsize=(16, 8), facecolor='#000000') |
|
|
ax.set_facecolor('#000000') |
|
|
ax.text(0.5, 0.5, 'No data available', |
|
|
horizontalalignment='center', verticalalignment='center', |
|
|
transform=ax.transAxes, fontsize=20, color='#888888', |
|
|
fontfamily='monospace', weight='normal') |
|
|
ax.axis('off') |
|
|
return fig |
|
|
|
|
|
|
|
|
model_count = len(available_models) |
|
|
columns = 3 |
|
|
rows = (model_count + columns - 1) // columns |
|
|
|
|
|
|
|
|
figure_width = 20 |
|
|
max_height = 12 |
|
|
height_per_row = min(2.2, max_height / max(rows, 1)) |
|
|
figure_height = min(max_height, rows * height_per_row + 2) |
|
|
|
|
|
fig, ax = plt.subplots(figsize=(figure_width, figure_height), facecolor='#000000') |
|
|
ax.set_facecolor('#000000') |
|
|
|
|
|
colors = { |
|
|
'passed': '#4CAF50', |
|
|
'failed': '#E53E3E', |
|
|
'skipped': '#FFD54F', |
|
|
'error': '#8B0000', |
|
|
'empty': "#5B5B5B" |
|
|
} |
|
|
|
|
|
visible_model_count = 0 |
|
|
max_y = 0 |
|
|
|
|
|
|
|
|
column_width = 100 / columns |
|
|
bar_width = column_width * 0.8 |
|
|
bar_margin = column_width * 0.1 |
|
|
|
|
|
for i, model_name in enumerate(available_models): |
|
|
if model_name not in df.index: |
|
|
continue |
|
|
|
|
|
row = df.loc[model_name] |
|
|
|
|
|
|
|
|
success_amd = int(row.get('success_amd', 0)) if pd.notna(row.get('success_amd', 0)) else 0 |
|
|
success_nvidia = int(row.get('success_nvidia', 0)) if pd.notna(row.get('success_nvidia', 0)) else 0 |
|
|
failed_multi_amd = int(row.get('failed_multi_no_amd', 0)) if pd.notna(row.get('failed_multi_no_amd', 0)) else 0 |
|
|
failed_multi_nvidia = int(row.get('failed_multi_no_nvidia', 0)) if pd.notna(row.get('failed_multi_no_nvidia', 0)) else 0 |
|
|
failed_single_amd = int(row.get('failed_single_no_amd', 0)) if pd.notna(row.get('failed_single_no_amd', 0)) else 0 |
|
|
failed_single_nvidia = int(row.get('failed_single_no_nvidia', 0)) if pd.notna(row.get('failed_single_no_nvidia', 0)) else 0 |
|
|
|
|
|
|
|
|
amd_stats = { |
|
|
'passed': success_amd, |
|
|
'failed': failed_multi_amd + failed_single_amd, |
|
|
'skipped': 0, |
|
|
'error': 0 |
|
|
} |
|
|
|
|
|
nvidia_stats = { |
|
|
'passed': success_nvidia, |
|
|
'failed': failed_multi_nvidia + failed_single_nvidia, |
|
|
'skipped': 0, |
|
|
'error': 0 |
|
|
} |
|
|
|
|
|
amd_total = sum(amd_stats.values()) |
|
|
nvidia_total = sum(nvidia_stats.values()) |
|
|
|
|
|
if amd_total == 0 and nvidia_total == 0: |
|
|
continue |
|
|
|
|
|
|
|
|
col = visible_model_count % columns |
|
|
row = visible_model_count // columns |
|
|
|
|
|
|
|
|
col_left = col * column_width + bar_margin |
|
|
col_center = col * column_width + column_width / 2 |
|
|
|
|
|
|
|
|
vertical_spacing = height_per_row |
|
|
y_base = (0.2 + row) * vertical_spacing |
|
|
y_model_name = y_base |
|
|
y_amd_bar = y_base + vertical_spacing * 0.25 |
|
|
y_nvidia_bar = y_base + vertical_spacing * 0.54 |
|
|
max_y = max(max_y, y_nvidia_bar + vertical_spacing * 0.3) |
|
|
|
|
|
|
|
|
ax.text(col_center, y_model_name, model_name.lower(), |
|
|
ha='center', va='center', color='#FFFFFF', |
|
|
fontsize=16, fontfamily='monospace', fontweight='bold') |
|
|
|
|
|
|
|
|
bar_height = min(0.4, vertical_spacing * 0.22) |
|
|
label_x = col_left - 1 |
|
|
ax.text(label_x, y_amd_bar, "amd", ha='right', va='center', color='#CCCCCC', fontsize=14, fontfamily='monospace', fontweight='normal') |
|
|
|
|
|
if amd_total > 0: |
|
|
|
|
|
left = col_left |
|
|
for category in ['passed', 'failed', 'skipped', 'error']: |
|
|
if amd_stats[category] > 0: |
|
|
width = amd_stats[category] / amd_total * bar_width |
|
|
ax.barh(y_amd_bar, width, left=left, height=bar_height, |
|
|
color=colors[category], alpha=0.9) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
left += width |
|
|
else: |
|
|
ax.barh(y_amd_bar, bar_width, left=col_left, height=bar_height, color=colors['empty'], alpha=0.9) |
|
|
|
|
|
|
|
|
|
|
|
ax.text(label_x, y_nvidia_bar, "nvidia", ha='right', va='center', color='#CCCCCC', fontsize=14, fontfamily='monospace', fontweight='normal') |
|
|
|
|
|
if nvidia_total > 0: |
|
|
|
|
|
left = col_left |
|
|
for category in ['passed', 'failed', 'skipped', 'error']: |
|
|
if nvidia_stats[category] > 0: |
|
|
width = nvidia_stats[category] / nvidia_total * bar_width |
|
|
ax.barh(y_nvidia_bar, width, left=left, height=bar_height, |
|
|
color=colors[category], alpha=0.9) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
left += width |
|
|
else: |
|
|
ax.barh(y_nvidia_bar, bar_width, left=col_left, height=bar_height, color=colors['empty'], alpha=0.9) |
|
|
|
|
|
|
|
|
|
|
|
visible_model_count += 1 |
|
|
|
|
|
|
|
|
ax.set_xlim(-5, 105) |
|
|
ax.set_ylim(0, max_y) |
|
|
ax.set_xlabel('') |
|
|
ax.set_ylabel('') |
|
|
ax.spines['bottom'].set_visible(False) |
|
|
ax.spines['left'].set_visible(False) |
|
|
ax.spines['top'].set_visible(False) |
|
|
ax.spines['right'].set_visible(False) |
|
|
ax.set_xticks([]) |
|
|
ax.set_yticks([]) |
|
|
ax.yaxis.set_inverted(True) |
|
|
|
|
|
|
|
|
plt.tight_layout() |
|
|
plt.subplots_adjust(left=0.02, right=0.98, top=1.0, bottom=0.02) |
|
|
|
|
|
return fig |
|
|
|