Skip to content

Commit 72e2a5b

Browse files
authored
Merge pull request #58 from johnramsden/sam/update-graphs
Sam/update graphs
2 parents 072cd4a + f3aba9e commit 72e2a5b

8 files changed

Lines changed: 128 additions & 105 deletions

eval/distribution_comparison_boxplots.py

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import data_cache
2020

2121
# Increase all font sizes by 16 points from their defaults
22-
rcParams.update({key: rcParams[key] + 16 for key in rcParams if "size" in key and isinstance(rcParams[key], (int, float))})
22+
rcParams.update({key: rcParams[key] + 32 for key in rcParams if "size" in key and isinstance(rcParams[key], (int, float))})
2323

2424
# ============================================================================
2525
# CONFIGURATION SECTION
@@ -249,26 +249,25 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o
249249

250250
print(f"Found {len(block_runs)} block runs and {len(zns_runs)} ZNS runs")
251251

252-
# Create figure with 6 subplots (1 row x 6 columns) using GridSpec for custom widths
252+
# Create figure with 6 subplots (2 rows x 3 columns) using GridSpec for custom widths
253253
# Subplots are 2/5 original height, but all spacing preserved
254-
num_subplots = len(RATIOS) * len(CHUNK_SIZES) # 2 ratios * 3 chunk sizes = 6
254+
num_ratios = len(RATIOS)
255+
num_chunk_sizes = len(CHUNK_SIZES)
255256

256-
# Width ratios: 1077MiB subplots (indices 2 and 5) are half as wide since they have 2 boxes instead of 4
257-
width_ratios = [1, 1, 0.5, 1, 1, 0.5]
257+
# Width ratios: 1077MiB subplots (column 2) are half as wide since they have 2 boxes instead of 4
258+
width_ratios = [1, 1, 0.5]
258259

259-
fig = plt.figure(figsize=(5 * num_subplots, 5.38))
260-
gs = GridSpec(1, num_subplots, figure=fig, width_ratios=width_ratios)
261-
axes = [fig.add_subplot(gs[0, i]) for i in range(num_subplots)]
260+
fig = plt.figure(figsize=(8.0 * num_chunk_sizes, 7.0 * num_ratios))
261+
gs = GridSpec(num_ratios, num_chunk_sizes, figure=fig, width_ratios=width_ratios)
262+
axes = [[fig.add_subplot(gs[i, j]) for j in range(num_chunk_sizes)] for i in range(num_ratios)]
262263

263264
# First pass: collect all data to find global maximum for y-axis
264265
all_subplot_data = []
265266
global_max = 0.0
266267

267-
idx = 0
268-
269268
# Iterate through ratios, then chunk sizes
270-
for ratio in RATIOS:
271-
for chunk_size in CHUNK_SIZES:
269+
for ratio_idx, ratio in enumerate(RATIOS):
270+
for chunk_idx, chunk_size in enumerate(CHUNK_SIZES):
272271
# Prepare data for this subplot
273272
current_data = []
274273
labels = []
@@ -364,7 +363,9 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o
364363
'labels': labels,
365364
'colors': colors,
366365
'hatches': hatches,
367-
'chunk_size': chunk_size
366+
'chunk_size': chunk_size,
367+
'ratio_idx': ratio_idx,
368+
'chunk_idx': chunk_idx
368369
})
369370

370371
# Update global maximum if using common scale
@@ -375,8 +376,6 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o
375376
if local_max > global_max:
376377
global_max = local_max
377378

378-
idx += 1
379-
380379
# Add some padding to the global max (10% above highest value)
381380
if common_y_scale:
382381
y_max = global_max * 1.1
@@ -385,13 +384,14 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o
385384
y_max = None
386385

387386
# Second pass: create boxplots with common y-axis
388-
idx = 0
389387
for subplot_info in all_subplot_data:
390388
current_data = subplot_info['data']
391389
labels = subplot_info['labels']
392390
colors = subplot_info['colors']
393391
hatches = subplot_info['hatches']
394392
chunk_size = subplot_info['chunk_size']
393+
ratio_idx = subplot_info['ratio_idx']
394+
chunk_idx = subplot_info['chunk_idx']
395395

396396
# Create boxplot for this subplot
397397
if current_data:
@@ -404,10 +404,13 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o
404404
else:
405405
box_width = 0.8 * (num_boxes / 4) if num_boxes > 0 else 0.8
406406

407-
bp = axes[idx].boxplot(current_data,
407+
bp = axes[ratio_idx][chunk_idx].boxplot(current_data,
408408
showfliers=show_outliers,
409409
widths=box_width,
410-
medianprops=dict(linewidth=2, color='black'),
410+
boxprops=dict(linewidth=3),
411+
whiskerprops=dict(linewidth=3),
412+
capprops=dict(linewidth=3),
413+
medianprops=dict(linewidth=3, color='black'),
411414
patch_artist=True)
412415

413416
# Apply colors and hatches
@@ -418,46 +421,45 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o
418421
box.set_alpha(0.7)
419422

420423
# Set x-axis labels (empty for cleaner look, or could add device labels)
421-
axes[idx].set_xticks(range(1, len(labels) + 1))
422-
axes[idx].set_xticklabels([], rotation=45, fontsize=10)
424+
axes[ratio_idx][chunk_idx].set_xticks(range(1, len(labels) + 1))
425+
axes[ratio_idx][chunk_idx].set_xticklabels([], rotation=45, fontsize=10)
423426

424427
# Add chunk size label below subplot
425-
axes[idx].set_xlabel(CHUNK_SIZE_LABELS[chunk_size], fontsize=28, weight='bold')
428+
axes[ratio_idx][chunk_idx].set_xlabel(CHUNK_SIZE_LABELS[chunk_size], fontsize=58, weight='bold')
426429

427430
# Use scalar formatter without scientific notation
428-
axes[idx].yaxis.set_major_formatter(ticker.ScalarFormatter(useOffset=False, useMathText=False))
431+
axes[ratio_idx][chunk_idx].yaxis.set_major_formatter(ticker.ScalarFormatter(useOffset=False, useMathText=False))
429432

430433
# Rotate y-axis labels
431-
for label in axes[idx].get_yticklabels():
434+
for label in axes[ratio_idx][chunk_idx].get_yticklabels():
432435
label.set_rotation(45)
433436

434437
# Set y-axis range
435438
if common_y_scale:
436439
# Use common y-axis maximum for all subplots
437-
axes[idx].set_ylim(0, y_max)
440+
axes[ratio_idx][chunk_idx].set_ylim(0, y_max)
438441
else:
439442
# Just set bottom to 0, let matplotlib auto-scale the top
440-
axes[idx].set_ylim(bottom=0)
441-
442-
idx += 1
443+
axes[ratio_idx][chunk_idx].set_ylim(bottom=0)
443444

444445
# Add y-axis label on the far left
445-
fig.text(-0.005, 0.5, metric_label, va='center', rotation='vertical', fontsize=22, weight='bold')
446+
fig.text(-0.065, 0.5, metric_label, va='center', rotation='vertical', fontsize=64, weight='bold')
446447

447448
# Adjust layout (do these BEFORE computing positions) - subplots at 2/5 height with proportional spacing
448-
plt.subplots_adjust(wspace=0.2, hspace=0.0)
449449
plt.tight_layout(pad=0.0)
450-
plt.subplots_adjust(top=0.851, bottom=0.279, left=0.05)
450+
plt.subplots_adjust(top=0.90, bottom=0.15, left=0.08, hspace=1.2, wspace=0.3)
451451

452452
# Make sure layout is finalized
453453
fig.canvas.draw()
454454

455455
# Compute positions for ratio boxes and labels based on actual subplot bounds
456-
axes_bboxes = [ax.get_position().bounds for ax in axes] # (x, y, w, h) per axes
456+
# Flatten the 2D axes array to get all subplot bounds
457+
axes_flat = [axes[i][j] for i in range(num_ratios) for j in range(num_chunk_sizes)]
458+
axes_bboxes = [ax.get_position().bounds for ax in axes_flat] # (x, y, w, h) per axes
457459

458-
# First 3 subplots -> Ratio 1:2, next 3 -> Ratio 1:10
459-
group1 = axes_bboxes[0:3]
460-
group2 = axes_bboxes[3:6]
460+
# First row (3 subplots) -> Ratio 1:2, second row (3 subplots) -> Ratio 1:10
461+
group1 = axes_bboxes[0:3] # First row
462+
group2 = axes_bboxes[3:6] # Second row
461463

462464
# Left/right bounds of each group
463465
g1_left = group1[0][0]
@@ -468,14 +470,21 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o
468470
g2_right = group2[-1][0] + group2[-1][2]
469471
g2_width = g2_right - g2_left
470472

471-
# Vertical placement of the grey boxes in figure coords
472-
box_y = 0.85
473-
box_h = 0.10
473+
# Vertical placement of the grey boxes - position above each row
474+
# Get the top y position of each row's subplots and add some padding
475+
g1_top = group1[0][1] + group1[0][3] # y + height of first row
476+
g2_top = group2[0][1] + group2[0][3] # y + height of second row
477+
478+
box_h = 0.06
479+
box_y_offset = 0.02 # Space above the subplot
480+
481+
g1_box_y = g1_top + box_y_offset
482+
g2_box_y = g2_top + box_y_offset
474483

475-
# Grey box for Ratio 1:2
484+
# Grey box for Ratio 1:2 (first row)
476485
fig.add_artist(
477486
Rectangle(
478-
(g1_left, box_y),
487+
(g1_left, g1_box_y),
479488
g1_width,
480489
box_h,
481490
transform=fig.transFigure,
@@ -487,10 +496,10 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o
487496
)
488497
)
489498

490-
# Grey box for Ratio 1:10
499+
# Grey box for Ratio 1:10 (second row)
491500
fig.add_artist(
492501
Rectangle(
493-
(g2_left, box_y),
502+
(g2_left, g2_box_y),
494503
g2_width,
495504
box_h,
496505
transform=fig.transFigure,
@@ -505,21 +514,21 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o
505514
# Centered text in each box
506515
fig.text(
507516
g1_left + g1_width / 2,
508-
box_y + box_h / 2,
517+
g1_box_y + box_h / 2,
509518
"Ratio: 1:2",
510519
ha='center',
511520
va='center',
512-
fontsize=26,
521+
fontsize=50,
513522
weight='bold',
514523
zorder=2,
515524
)
516525
fig.text(
517526
g2_left + g2_width / 2,
518-
box_y + box_h / 2,
527+
g2_box_y + box_h / 2,
519528
"Ratio: 1:10",
520529
ha='center',
521530
va='center',
522-
fontsize=26,
531+
fontsize=50,
523532
weight='bold',
524533
zorder=2,
525534
)
@@ -533,9 +542,9 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o
533542
]
534543

535544
fig.legend(
536-
ncols=4,
545+
ncols=2,
537546
handles=legend_patches,
538-
bbox_to_anchor=(0.5, 0.08),
547+
bbox_to_anchor=(0.5, -0.08),
539548
loc='center',
540549
fontsize="large",
541550
columnspacing=2.0,

0 commit comments

Comments
 (0)