justinkay
commited on
Commit
·
f6dfc71
1
Parent(s):
3df076d
Style changes to accuracy plot
Browse files
app.py
CHANGED
|
@@ -224,11 +224,13 @@ def get_next_coda_image():
|
|
| 224 |
|
| 225 |
# Get next item from CODA
|
| 226 |
chosen_idx, selection_prob = coda_selector.get_next_item_to_label()
|
|
|
|
| 227 |
|
| 228 |
# Get the corresponding image filename
|
| 229 |
if chosen_idx < len(image_filenames):
|
| 230 |
filename = image_filenames[chosen_idx]
|
| 231 |
image_path = os.path.join('iwildcam_demo_images', filename)
|
|
|
|
| 232 |
|
| 233 |
# Find the corresponding annotation for this image
|
| 234 |
current_image_info = None
|
|
@@ -475,12 +477,26 @@ def create_accuracy_bar_chart():
|
|
| 475 |
|
| 476 |
fig, ax = plt.subplots(figsize=(8, 2.8), dpi=150)
|
| 477 |
|
| 478 |
-
#
|
| 479 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 480 |
|
| 481 |
ax.set_ylabel('True (oracle) \naccuracy of model', fontsize=12)
|
| 482 |
ax.set_title('True Model Accuracies', fontsize=12)
|
| 483 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 484 |
|
| 485 |
# Set x-axis labels and ticks
|
| 486 |
ax.set_xticks(range(len(model_labels)))
|
|
@@ -747,7 +763,9 @@ with gr.Blocks(title="CODA: Wildlife Photo Classification Challenge",
|
|
| 747 |
.subtle-outline * {
|
| 748 |
color: var(--body-text-color) !important;
|
| 749 |
}
|
| 750 |
-
"""
|
|
|
|
|
|
|
| 751 |
# Main page title
|
| 752 |
gr.Markdown("# CODA: Consensus-Driven Active Model Selection", elem_classes="text-center")
|
| 753 |
gr.Markdown("*Figure out which model is best by actively annotating data.*", elem_classes="text-center")
|
|
@@ -901,7 +919,7 @@ with gr.Blocks(title="CODA: Wildlife Photo Classification Challenge",
|
|
| 901 |
# gr.HTML("<div style='margin-top: 2.9em;'></div>")
|
| 902 |
|
| 903 |
hidden_text0 = gr.Markdown("""
|
| 904 |
-
|
| 905 |
""",
|
| 906 |
elem_classes="text-center",)
|
| 907 |
|
|
@@ -948,7 +966,8 @@ with gr.Blocks(title="CODA: Wildlife Photo Classification Challenge",
|
|
| 948 |
label="Identify this animal:",
|
| 949 |
value=None,
|
| 950 |
height=400,
|
| 951 |
-
width=550
|
|
|
|
| 952 |
)
|
| 953 |
|
| 954 |
# Model predictions panel (full width, single line)
|
|
@@ -1328,12 +1347,13 @@ with gr.Blocks(title="CODA: Wildlife Photo Classification Challenge",
|
|
| 1328 |
outputs=[result_display, image_display, model_predictions_display, prob_plot, accuracy_plot, status_with_help]
|
| 1329 |
)
|
| 1330 |
|
| 1331 |
-
# Add JavaScript to handle inline help button clicks
|
| 1332 |
demo.load(
|
| 1333 |
lambda: None,
|
| 1334 |
outputs=[],
|
| 1335 |
js="""
|
| 1336 |
() => {
|
|
|
|
| 1337 |
setTimeout(() => {
|
| 1338 |
document.addEventListener('click', function(e) {
|
| 1339 |
if (e.target && e.target.classList.contains('inline-help-btn')) {
|
|
@@ -1346,13 +1366,64 @@ with gr.Blocks(title="CODA: Wildlife Photo Classification Challenge",
|
|
| 1346 |
}
|
| 1347 |
});
|
| 1348 |
}, 100);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1349 |
}
|
| 1350 |
-
"""
|
| 1351 |
)
|
| 1352 |
|
| 1353 |
if __name__ == "__main__":
|
| 1354 |
demo.launch(
|
| 1355 |
# share=True,
|
| 1356 |
# server_port=7861,
|
| 1357 |
-
allowed_paths=["/"]
|
| 1358 |
)
|
|
|
|
| 224 |
|
| 225 |
# Get next item from CODA
|
| 226 |
chosen_idx, selection_prob = coda_selector.get_next_item_to_label()
|
| 227 |
+
print("CODA chosen_idx, selection prob:", chosen_idx, selection_prob)
|
| 228 |
|
| 229 |
# Get the corresponding image filename
|
| 230 |
if chosen_idx < len(image_filenames):
|
| 231 |
filename = image_filenames[chosen_idx]
|
| 232 |
image_path = os.path.join('iwildcam_demo_images', filename)
|
| 233 |
+
print("Next image is", filename)
|
| 234 |
|
| 235 |
# Find the corresponding annotation for this image
|
| 236 |
current_image_info = None
|
|
|
|
| 477 |
|
| 478 |
fig, ax = plt.subplots(figsize=(8, 2.8), dpi=150)
|
| 479 |
|
| 480 |
+
# Create colors array - highlight the best model with a significantly darker shade
|
| 481 |
+
colors = ['#4B6D98' if i == best_idx else '#8B9DC3' for i in range(len(model_labels))]
|
| 482 |
+
bars = ax.bar(range(len(model_labels)), accuracies, color=colors, alpha=0.7)
|
| 483 |
+
|
| 484 |
+
# Add text above the highest bar
|
| 485 |
+
ax.text(best_idx, accuracies[best_idx] + 0.0025, 'True best model',
|
| 486 |
+
ha='center', va='bottom', fontsize=12, fontweight='bold')
|
| 487 |
|
| 488 |
ax.set_ylabel('True (oracle) \naccuracy of model', fontsize=12)
|
| 489 |
ax.set_title('True Model Accuracies', fontsize=12)
|
| 490 |
+
y_min = np.min(accuracies) - 0.025
|
| 491 |
+
y_max = np.max(accuracies) + 0.05
|
| 492 |
+
ax.set_ylim(y_min, y_max)
|
| 493 |
+
|
| 494 |
+
# Add accuracy values in the middle of the visible portion of each bar
|
| 495 |
+
for i, (bar, acc) in enumerate(zip(bars, accuracies)):
|
| 496 |
+
# Position text in the middle of the visible part of the bar
|
| 497 |
+
text_y = (y_min + acc) / 2
|
| 498 |
+
ax.text(i, text_y, f'{acc:.3f}',
|
| 499 |
+
ha='center', va='center', fontsize=10, fontweight='bold', color='white')
|
| 500 |
|
| 501 |
# Set x-axis labels and ticks
|
| 502 |
ax.set_xticks(range(len(model_labels)))
|
|
|
|
| 763 |
.subtle-outline * {
|
| 764 |
color: var(--body-text-color) !important;
|
| 765 |
}
|
| 766 |
+
""",
|
| 767 |
+
delete_cache=(3600,3600) # once per hour - clear old javascript
|
| 768 |
+
) as demo:
|
| 769 |
# Main page title
|
| 770 |
gr.Markdown("# CODA: Consensus-Driven Active Model Selection", elem_classes="text-center")
|
| 771 |
gr.Markdown("*Figure out which model is best by actively annotating data.*", elem_classes="text-center")
|
|
|
|
| 919 |
# gr.HTML("<div style='margin-top: 2.9em;'></div>")
|
| 920 |
|
| 921 |
hidden_text0 = gr.Markdown("""
|
| 922 |
+
## True model performance is hidden
|
| 923 |
""",
|
| 924 |
elem_classes="text-center",)
|
| 925 |
|
|
|
|
| 966 |
label="Identify this animal:",
|
| 967 |
value=None,
|
| 968 |
height=400,
|
| 969 |
+
width=550,
|
| 970 |
+
elem_id="main-image-display"
|
| 971 |
)
|
| 972 |
|
| 973 |
# Model predictions panel (full width, single line)
|
|
|
|
| 1347 |
outputs=[result_display, image_display, model_predictions_display, prob_plot, accuracy_plot, status_with_help]
|
| 1348 |
)
|
| 1349 |
|
| 1350 |
+
# Add JavaScript to handle inline help button clicks and dynamic image sizing
|
| 1351 |
demo.load(
|
| 1352 |
lambda: None,
|
| 1353 |
outputs=[],
|
| 1354 |
js="""
|
| 1355 |
() => {
|
| 1356 |
+
// Handle inline help button clicks
|
| 1357 |
setTimeout(() => {
|
| 1358 |
document.addEventListener('click', function(e) {
|
| 1359 |
if (e.target && e.target.classList.contains('inline-help-btn')) {
|
|
|
|
| 1366 |
}
|
| 1367 |
});
|
| 1368 |
}, 100);
|
| 1369 |
+
|
| 1370 |
+
// Dynamic image sizing (NEW VERSION)
|
| 1371 |
+
console.log('=== IMAGE SIZING V2 LOADED ===');
|
| 1372 |
+
|
| 1373 |
+
function adjustImageSize() {
|
| 1374 |
+
const imageContainer = document.getElementById('main-image-display');
|
| 1375 |
+
if (!imageContainer) {
|
| 1376 |
+
console.log('[V2] Image container not found');
|
| 1377 |
+
return false;
|
| 1378 |
+
}
|
| 1379 |
+
|
| 1380 |
+
const viewportHeight = window.innerHeight;
|
| 1381 |
+
const docHeight = document.documentElement.scrollHeight;
|
| 1382 |
+
const currentImageHeight = imageContainer.offsetHeight;
|
| 1383 |
+
|
| 1384 |
+
// Calculate how much we're overflowing
|
| 1385 |
+
const overflow = docHeight - viewportHeight;
|
| 1386 |
+
|
| 1387 |
+
// If we're not overflowing, increase image size
|
| 1388 |
+
// If we are overflowing, decrease image size by the overflow amount
|
| 1389 |
+
const adjustment = -overflow - 30; // Keep padding below bottom button
|
| 1390 |
+
const targetHeight = currentImageHeight + adjustment;
|
| 1391 |
+
|
| 1392 |
+
console.log('[V2] viewport:', viewportHeight, 'docHeight:', docHeight, 'currentImg:', currentImageHeight, 'overflow:', overflow, 'target:', targetHeight);
|
| 1393 |
+
|
| 1394 |
+
// Only apply if reasonable
|
| 1395 |
+
if (targetHeight > 300 && targetHeight < viewportHeight - 100) {
|
| 1396 |
+
imageContainer.style.height = targetHeight + 'px';
|
| 1397 |
+
imageContainer.style.maxHeight = targetHeight + 'px';
|
| 1398 |
+
console.log('[V2] Set image height to:', targetHeight + 'px');
|
| 1399 |
+
return true;
|
| 1400 |
+
}
|
| 1401 |
+
|
| 1402 |
+
return false;
|
| 1403 |
+
}
|
| 1404 |
+
|
| 1405 |
+
// Run after initial load
|
| 1406 |
+
setTimeout(adjustImageSize, 500);
|
| 1407 |
+
|
| 1408 |
+
// Run periodically for first 5 seconds to catch layout changes
|
| 1409 |
+
let attempts = 0;
|
| 1410 |
+
const interval = setInterval(() => {
|
| 1411 |
+
attempts++;
|
| 1412 |
+
adjustImageSize();
|
| 1413 |
+
if (attempts >= 50) { // 50 * 100ms = 5 seconds
|
| 1414 |
+
clearInterval(interval);
|
| 1415 |
+
}
|
| 1416 |
+
}, 100);
|
| 1417 |
+
|
| 1418 |
+
// Re-adjust on window resize
|
| 1419 |
+
window.addEventListener('resize', adjustImageSize);
|
| 1420 |
}
|
| 1421 |
+
""",
|
| 1422 |
)
|
| 1423 |
|
| 1424 |
if __name__ == "__main__":
|
| 1425 |
demo.launch(
|
| 1426 |
# share=True,
|
| 1427 |
# server_port=7861,
|
| 1428 |
+
allowed_paths=["/"],
|
| 1429 |
)
|