tcid / summary_page.py
ror's picture
ror HF Staff
Better top alignment
3c0dd4c
raw
history blame
7.73 kB
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
# Calculate dimensions for N-column layout
model_count = len(available_models)
columns = 3
rows = (model_count + columns - 1) // columns # Ceiling division
# Figure dimensions - wider for 4 columns, height based on rows
figure_width = 20 # Wider to accommodate 4 columns
max_height = 12 # Maximum height in inches
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 layout parameters
column_width = 100 / columns # Each column takes 25% of width
bar_width = column_width * 0.8 # 80% of column width for bars
bar_margin = column_width * 0.1 # 10% margin on each side
for i, model_name in enumerate(available_models):
if model_name not in df.index:
continue
row = df.loc[model_name]
# Get values directly from dataframe
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
# Calculate stats
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
# Calculate position in 4-column grid
col = visible_model_count % columns
row = visible_model_count // columns
# Calculate horizontal position for this column
col_left = col * column_width + bar_margin
col_center = col * column_width + column_width / 2
# Calculate vertical position for this row - start from top
vertical_spacing = height_per_row
y_base = (0.2 + row) * vertical_spacing # Start closer to top
y_model_name = y_base # Model name above AMD bar
y_amd_bar = y_base + vertical_spacing * 0.25 # AMD bar
y_nvidia_bar = y_base + vertical_spacing * 0.54 # NVIDIA bar
max_y = max(max_y, y_nvidia_bar + vertical_spacing * 0.3)
# Model name centered above the bars in this column
ax.text(col_center, y_model_name, model_name.lower(),
ha='center', va='center', color='#FFFFFF',
fontsize=16, fontfamily='monospace', fontweight='bold')
# AMD label and bar in this column
bar_height = min(0.4, vertical_spacing * 0.22) # Adjust bar height based on spacing
label_x = col_left - 1 # Label position to the left of the bar
ax.text(label_x, y_amd_bar, "amd", ha='right', va='center', color='#CCCCCC', fontsize=14, fontfamily='monospace', fontweight='normal')
if amd_total > 0:
# AMD bar starts at column left position
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)
# if width > 2: # Smaller threshold for text display
# ax.text(left + width/2, y_amd_bar, str(amd_stats[category]),
# ha='center', va='center', color='black',
# fontweight='bold', fontsize=10, fontfamily='monospace')
left += width
else:
ax.barh(y_amd_bar, bar_width, left=col_left, height=bar_height, color=colors['empty'], alpha=0.9)
# ax.text(col_center, y_amd_bar, "No data", ha='center', va='center', color='black', fontweight='bold', fontsize=10, fontfamily='monospace')
# NVIDIA label and bar in this column
ax.text(label_x, y_nvidia_bar, "nvidia", ha='right', va='center', color='#CCCCCC', fontsize=14, fontfamily='monospace', fontweight='normal')
if nvidia_total > 0:
# NVIDIA bar starts at column left position
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)
# if width > 2: # Smaller threshold for text display
# ax.text(left + width/2, y_nvidia_bar, str(nvidia_stats[category]),
# ha='center', va='center', color='black',
# fontweight='bold', fontsize=10, fontfamily='monospace')
left += width
else:
ax.barh(y_nvidia_bar, bar_width, left=col_left, height=bar_height, color=colors['empty'], alpha=0.9)
# ax.text(col_center, y_nvidia_bar, "No data", ha='center', va='center', color='black', fontweight='bold', fontsize=10, fontfamily='monospace')
# Increment counter for next visible model
visible_model_count += 1
# Style the axes to be completely invisible and span full width
ax.set_xlim(-5, 105) # Slightly wider to accommodate labels
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)
# Remove all margins to make figure stick to top
plt.tight_layout()
plt.subplots_adjust(left=0.02, right=0.98, top=1.0, bottom=0.02)
return fig