Spaces:
Sleeping
Sleeping
Two pies, ok sidebar
Browse files
app.py
CHANGED
|
@@ -15,64 +15,110 @@ def plot_model_stats(model_name: str) -> plt.Figure:
|
|
| 15 |
"""Draws a pie chart of model's passed, failed, skipped, and error stats."""
|
| 16 |
model_stats = MODELS[model_name]
|
| 17 |
|
| 18 |
-
#
|
| 19 |
colors = {
|
| 20 |
-
'passed': '#4CAF50', #
|
| 21 |
-
'failed': '#
|
| 22 |
-
'skipped': '#
|
| 23 |
-
'error': '#
|
| 24 |
}
|
| 25 |
|
| 26 |
# Filter out categories with 0 values for cleaner visualization
|
| 27 |
filtered_stats = {k: v for k, v in model_stats.items() if v > 0}
|
| 28 |
|
| 29 |
if not filtered_stats:
|
| 30 |
-
# Handle case where all values are 0 -
|
| 31 |
fig, ax = plt.subplots(figsize=(10, 8), facecolor='#000000')
|
| 32 |
ax.set_facecolor('#000000')
|
| 33 |
ax.text(0.5, 0.5, 'No test results available',
|
| 34 |
horizontalalignment='center', verticalalignment='center',
|
| 35 |
-
transform=ax.transAxes, fontsize=16, color='
|
|
|
|
| 36 |
ax.set_xlim(0, 1)
|
| 37 |
ax.set_ylim(0, 1)
|
| 38 |
ax.axis('off')
|
| 39 |
return fig
|
| 40 |
|
| 41 |
-
# Create
|
| 42 |
-
fig,
|
| 43 |
-
|
|
|
|
| 44 |
|
| 45 |
# Get colors for filtered categories
|
| 46 |
chart_colors = [colors[category] for category in filtered_stats.keys()]
|
| 47 |
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
|
| 60 |
-
#
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
|
| 66 |
-
#
|
| 67 |
total_tests = sum(model_stats.values())
|
| 68 |
-
|
| 69 |
-
fontsize=18, weight='
|
|
|
|
| 70 |
|
| 71 |
-
#
|
| 72 |
plt.tight_layout()
|
|
|
|
| 73 |
|
| 74 |
return fig
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
# Custom CSS for dark theme
|
| 77 |
dark_theme_css = """
|
| 78 |
/* Global dark theme */
|
|
@@ -89,13 +135,82 @@ dark_theme_css = """
|
|
| 89 |
|
| 90 |
/* Sidebar styling */
|
| 91 |
.sidebar {
|
| 92 |
-
background
|
| 93 |
border: none !important;
|
| 94 |
-
padding:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 95 |
}
|
| 96 |
|
| 97 |
-
|
| 98 |
-
.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
background-color: #222222 !important;
|
| 100 |
color: white !important;
|
| 101 |
border: 1px solid #444444 !important;
|
|
@@ -104,7 +219,7 @@ dark_theme_css = """
|
|
| 104 |
transition: all 0.3s ease !important;
|
| 105 |
}
|
| 106 |
|
| 107 |
-
.gr-button:hover {
|
| 108 |
background-color: #333333 !important;
|
| 109 |
border-color: #666666 !important;
|
| 110 |
}
|
|
@@ -120,6 +235,41 @@ h1, h2, h3, p, .markdown {
|
|
| 120 |
color: white !important;
|
| 121 |
}
|
| 122 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
/* Remove all borders globally */
|
| 124 |
* {
|
| 125 |
border-color: transparent !important;
|
|
@@ -129,6 +279,7 @@ h1, h2, h3, p, .markdown {
|
|
| 129 |
.main-content {
|
| 130 |
background-color: #000000 !important;
|
| 131 |
padding: 20px !important;
|
|
|
|
| 132 |
}
|
| 133 |
"""
|
| 134 |
|
|
@@ -138,14 +289,14 @@ with gr.Blocks(title="Model Test Results Dashboard", css=dark_theme_css) as demo
|
|
| 138 |
with gr.Row():
|
| 139 |
# Sidebar for model selection
|
| 140 |
with gr.Column(scale=1, elem_classes=["sidebar"]):
|
| 141 |
-
gr.Markdown("#
|
| 142 |
-
gr.Markdown("Select a model to
|
| 143 |
|
| 144 |
# Model selection buttons in sidebar
|
| 145 |
model_buttons = []
|
| 146 |
for model_name in MODELS.keys():
|
| 147 |
btn = gr.Button(
|
| 148 |
-
f"
|
| 149 |
variant="secondary",
|
| 150 |
size="lg",
|
| 151 |
elem_classes=["model-button"]
|
|
|
|
| 15 |
"""Draws a pie chart of model's passed, failed, skipped, and error stats."""
|
| 16 |
model_stats = MODELS[model_name]
|
| 17 |
|
| 18 |
+
# Softer color palette - less pastel, more vibrant
|
| 19 |
colors = {
|
| 20 |
+
'passed': '#4CAF50', # Medium green
|
| 21 |
+
'failed': '#E53E3E', # More red
|
| 22 |
+
'skipped': '#FFD54F', # Medium yellow
|
| 23 |
+
'error': '#8B0000' # Dark red
|
| 24 |
}
|
| 25 |
|
| 26 |
# Filter out categories with 0 values for cleaner visualization
|
| 27 |
filtered_stats = {k: v for k, v in model_stats.items() if v > 0}
|
| 28 |
|
| 29 |
if not filtered_stats:
|
| 30 |
+
# Handle case where all values are 0 - minimal empty state
|
| 31 |
fig, ax = plt.subplots(figsize=(10, 8), facecolor='#000000')
|
| 32 |
ax.set_facecolor('#000000')
|
| 33 |
ax.text(0.5, 0.5, 'No test results available',
|
| 34 |
horizontalalignment='center', verticalalignment='center',
|
| 35 |
+
transform=ax.transAxes, fontsize=16, color='#888888',
|
| 36 |
+
fontfamily='monospace', weight='normal')
|
| 37 |
ax.set_xlim(0, 1)
|
| 38 |
ax.set_ylim(0, 1)
|
| 39 |
ax.axis('off')
|
| 40 |
return fig
|
| 41 |
|
| 42 |
+
# Create figure with two subplots side by side with padding
|
| 43 |
+
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(18, 9), facecolor='#000000')
|
| 44 |
+
ax1.set_facecolor('#000000')
|
| 45 |
+
ax2.set_facecolor('#000000')
|
| 46 |
|
| 47 |
# Get colors for filtered categories
|
| 48 |
chart_colors = [colors[category] for category in filtered_stats.keys()]
|
| 49 |
|
| 50 |
+
def create_pie_chart(ax, device_label):
|
| 51 |
+
# Create minimal pie chart - full pie, no donut effect
|
| 52 |
+
wedges, texts, autotexts = ax.pie(
|
| 53 |
+
filtered_stats.values(),
|
| 54 |
+
labels=[label.lower() for label in filtered_stats.keys()], # Lowercase for minimal look
|
| 55 |
+
colors=chart_colors,
|
| 56 |
+
autopct='%1.1f%%',
|
| 57 |
+
startangle=90,
|
| 58 |
+
explode=None, # No separation
|
| 59 |
+
shadow=False,
|
| 60 |
+
wedgeprops=dict(edgecolor='#1a1a1a', linewidth=0.5), # Minimal borders
|
| 61 |
+
textprops={'fontsize': 12, 'weight': 'normal', 'color': '#CCCCCC', 'fontfamily': 'monospace'}
|
| 62 |
+
)
|
| 63 |
+
|
| 64 |
+
# Enhanced percentage text styling for better readability
|
| 65 |
+
for autotext in autotexts:
|
| 66 |
+
autotext.set_color('#000000') # Black text for better contrast
|
| 67 |
+
autotext.set_weight('bold')
|
| 68 |
+
autotext.set_fontsize(14)
|
| 69 |
+
autotext.set_fontfamily('monospace')
|
| 70 |
+
|
| 71 |
+
# Minimal category labels
|
| 72 |
+
for text in texts:
|
| 73 |
+
text.set_color('#AAAAAA')
|
| 74 |
+
text.set_weight('normal')
|
| 75 |
+
text.set_fontsize(13)
|
| 76 |
+
text.set_fontfamily('monospace')
|
| 77 |
+
|
| 78 |
+
# Device label closer to chart and bigger
|
| 79 |
+
ax.set_title(device_label,
|
| 80 |
+
fontsize=28, weight='bold', pad=2, color='#FFFFFF',
|
| 81 |
+
fontfamily='monospace')
|
| 82 |
+
|
| 83 |
+
# Create both pie charts with device labels
|
| 84 |
+
create_pie_chart(ax1, "AMD")
|
| 85 |
+
create_pie_chart(ax2, "Nvidia")
|
| 86 |
|
| 87 |
+
# Add subtle separation line between charts
|
| 88 |
+
line_x = 0.5
|
| 89 |
+
fig.add_artist(plt.Line2D([line_x, line_x], [0.15, 0.8],
|
| 90 |
+
color='#333333', linewidth=1, alpha=0.5,
|
| 91 |
+
transform=fig.transFigure))
|
| 92 |
|
| 93 |
+
# Add central shared title for model name and test count
|
| 94 |
total_tests = sum(model_stats.values())
|
| 95 |
+
fig.suptitle(f'{model_name.lower()} • {total_tests} tests',
|
| 96 |
+
fontsize=18, weight='normal', color='#CCCCCC',
|
| 97 |
+
fontfamily='monospace', y=0.95)
|
| 98 |
|
| 99 |
+
# Clean layout with padding and space for central title
|
| 100 |
plt.tight_layout()
|
| 101 |
+
plt.subplots_adjust(top=0.85, wspace=0.4) # Added wspace for padding between charts
|
| 102 |
|
| 103 |
return fig
|
| 104 |
|
| 105 |
+
def get_model_stats_summary(model_name: str) -> tuple:
|
| 106 |
+
"""Get summary stats for a model (total tests, success rate, status indicator)."""
|
| 107 |
+
stats = MODELS[model_name]
|
| 108 |
+
total = sum(stats.values())
|
| 109 |
+
passed = stats['passed']
|
| 110 |
+
success_rate = (passed / total * 100) if total > 0 else 0
|
| 111 |
+
|
| 112 |
+
# Determine status indicator color
|
| 113 |
+
if success_rate >= 80:
|
| 114 |
+
status_class = "success-high"
|
| 115 |
+
elif success_rate >= 50:
|
| 116 |
+
status_class = "success-medium"
|
| 117 |
+
else:
|
| 118 |
+
status_class = "success-low"
|
| 119 |
+
|
| 120 |
+
return total, success_rate, status_class
|
| 121 |
+
|
| 122 |
# Custom CSS for dark theme
|
| 123 |
dark_theme_css = """
|
| 124 |
/* Global dark theme */
|
|
|
|
| 135 |
|
| 136 |
/* Sidebar styling */
|
| 137 |
.sidebar {
|
| 138 |
+
background: linear-gradient(145deg, #111111, #1a1a1a) !important;
|
| 139 |
border: none !important;
|
| 140 |
+
padding: 25px !important;
|
| 141 |
+
box-shadow: inset 2px 2px 5px rgba(0, 0, 0, 0.3) !important;
|
| 142 |
+
margin: 0 !important;
|
| 143 |
+
height: 100vh !important;
|
| 144 |
+
position: fixed !important;
|
| 145 |
+
left: 0 !important;
|
| 146 |
+
top: 0 !important;
|
| 147 |
+
width: 300px !important;
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
/* Enhanced model button styling */
|
| 151 |
+
.model-button {
|
| 152 |
+
background: linear-gradient(135deg, #2a2a2a, #1e1e1e) !important;
|
| 153 |
+
color: white !important;
|
| 154 |
+
border: 2px solid transparent !important;
|
| 155 |
+
margin: 2px 0 !important;
|
| 156 |
+
border-radius: 5px !important;
|
| 157 |
+
padding: 8px 12px !important;
|
| 158 |
+
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
| 159 |
+
position: relative !important;
|
| 160 |
+
overflow: hidden !important;
|
| 161 |
+
box-shadow:
|
| 162 |
+
0 4px 15px rgba(0, 0, 0, 0.2),
|
| 163 |
+
inset 0 1px 0 rgba(255, 255, 255, 0.1) !important;
|
| 164 |
+
font-weight: 600 !important;
|
| 165 |
+
font-size: 16px !important;
|
| 166 |
+
text-transform: uppercase !important;
|
| 167 |
+
letter-spacing: 0.5px !important;
|
| 168 |
+
font-family: monospace !important;
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
.model-button:hover {
|
| 172 |
+
background: linear-gradient(135deg, #3a3a3a, #2e2e2e) !important;
|
| 173 |
+
color: #74b9ff !important;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
.model-button:active {
|
| 177 |
+
background: linear-gradient(135deg, #2a2a2a, #1e1e1e) !important;
|
| 178 |
+
color: #5a9bd4 !important;
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
/* Model stats badge */
|
| 182 |
+
.model-stats {
|
| 183 |
+
display: flex !important;
|
| 184 |
+
justify-content: space-between !important;
|
| 185 |
+
align-items: center !important;
|
| 186 |
+
margin-top: 8px !important;
|
| 187 |
+
font-size: 12px !important;
|
| 188 |
+
opacity: 0.8 !important;
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
.stats-badge {
|
| 192 |
+
background: rgba(116, 185, 255, 0.2) !important;
|
| 193 |
+
padding: 4px 8px !important;
|
| 194 |
+
border-radius: 10px !important;
|
| 195 |
+
font-weight: 500 !important;
|
| 196 |
+
font-size: 11px !important;
|
| 197 |
+
color: #74b9ff !important;
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
.success-indicator {
|
| 201 |
+
width: 8px !important;
|
| 202 |
+
height: 8px !important;
|
| 203 |
+
border-radius: 50% !important;
|
| 204 |
+
display: inline-block !important;
|
| 205 |
+
margin-right: 6px !important;
|
| 206 |
}
|
| 207 |
|
| 208 |
+
.success-high { background-color: #4CAF50 !important; }
|
| 209 |
+
.success-medium { background-color: #FF9800 !important; }
|
| 210 |
+
.success-low { background-color: #F44336 !important; }
|
| 211 |
+
|
| 212 |
+
/* Regular button styling for non-model buttons */
|
| 213 |
+
.gr-button:not(.model-button) {
|
| 214 |
background-color: #222222 !important;
|
| 215 |
color: white !important;
|
| 216 |
border: 1px solid #444444 !important;
|
|
|
|
| 219 |
transition: all 0.3s ease !important;
|
| 220 |
}
|
| 221 |
|
| 222 |
+
.gr-button:not(.model-button):hover {
|
| 223 |
background-color: #333333 !important;
|
| 224 |
border-color: #666666 !important;
|
| 225 |
}
|
|
|
|
| 235 |
color: white !important;
|
| 236 |
}
|
| 237 |
|
| 238 |
+
/* Sidebar header enhancement */
|
| 239 |
+
.sidebar h1 {
|
| 240 |
+
background: linear-gradient(45deg, #74b9ff, #a29bfe) !important;
|
| 241 |
+
-webkit-background-clip: text !important;
|
| 242 |
+
-webkit-text-fill-color: transparent !important;
|
| 243 |
+
background-clip: text !important;
|
| 244 |
+
text-align: center !important;
|
| 245 |
+
margin-bottom: 15px !important;
|
| 246 |
+
font-size: 28px !important;
|
| 247 |
+
font-weight: 700 !important;
|
| 248 |
+
font-family: monospace !important;
|
| 249 |
+
}
|
| 250 |
+
|
| 251 |
+
/* Sidebar description text */
|
| 252 |
+
.sidebar p {
|
| 253 |
+
text-align: center !important;
|
| 254 |
+
margin-bottom: 20px !important;
|
| 255 |
+
line-height: 1.5 !important;
|
| 256 |
+
font-size: 14px !important;
|
| 257 |
+
font-family: monospace !important;
|
| 258 |
+
}
|
| 259 |
+
|
| 260 |
+
.sidebar strong {
|
| 261 |
+
color: #74b9ff !important;
|
| 262 |
+
font-weight: 600 !important;
|
| 263 |
+
font-family: monospace !important;
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
.sidebar em {
|
| 267 |
+
color: #a29bfe !important;
|
| 268 |
+
font-style: normal !important;
|
| 269 |
+
opacity: 0.9 !important;
|
| 270 |
+
font-family: monospace !important;
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
/* Remove all borders globally */
|
| 274 |
* {
|
| 275 |
border-color: transparent !important;
|
|
|
|
| 279 |
.main-content {
|
| 280 |
background-color: #000000 !important;
|
| 281 |
padding: 20px !important;
|
| 282 |
+
margin-left: 300px !important;
|
| 283 |
}
|
| 284 |
"""
|
| 285 |
|
|
|
|
| 289 |
with gr.Row():
|
| 290 |
# Sidebar for model selection
|
| 291 |
with gr.Column(scale=1, elem_classes=["sidebar"]):
|
| 292 |
+
gr.Markdown("# 🤖 AI Models")
|
| 293 |
+
gr.Markdown("**Select a model to analyze test results**\n\n*Interactive dashboard with detailed metrics*")
|
| 294 |
|
| 295 |
# Model selection buttons in sidebar
|
| 296 |
model_buttons = []
|
| 297 |
for model_name in MODELS.keys():
|
| 298 |
btn = gr.Button(
|
| 299 |
+
f"{model_name.lower()}",
|
| 300 |
variant="secondary",
|
| 301 |
size="lg",
|
| 302 |
elem_classes=["model-button"]
|