Spaces:
Running
Running
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"]
|