Skip to content

Commit 0042ecb

Browse files
committed
Enh(llm as judge): Update figure styling
1 parent 70346c2 commit 0042ecb

1 file changed

Lines changed: 133 additions & 73 deletions

File tree

codeclash/analysis/llm_as_judge/grounding_validation_triple_plot.py

100644100755
Lines changed: 133 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#!/usr/bin/env python3
2+
13
import argparse
24
from collections import defaultdict
35
from pathlib import Path
@@ -6,27 +8,27 @@
68
import numpy as np
79
import pandas as pd
810

9-
from codeclash.analysis.viz.utils import MODEL_TO_DISPLAY_NAME
11+
from codeclash.analysis.viz.utils import FONT_BOLD, FONT_REG, MODEL_TO_DISPLAY_NAME
1012

1113

1214
class GroundingValidationPlotter:
1315
"""Create a triple plot showing grounding, validation, and testing/analysis metrics."""
1416

1517
# Styling parameters
1618
title_fontsize = 16
17-
title_pad = 10
19+
title_pad = 45
1820
legend_fontsize = 14
21+
legend_title_fontsize = 12
1922
label_fontsize = 14
20-
ytick_label_fontsize = 14
21-
xtick_label_fontsize = 12
23+
ytick_label_fontsize = 15
24+
xtick_label_fontsize = 14
2225
in_bar_number_fontsize = 12
2326
in_bar_number_fontweight = "bold"
2427
total_number_fontsize = 12
2528
total_number_fontweight = "bold"
2629

2730
# Spacing parameters
2831
bar_height = 0.8 # Height of each bar (higher = less space between bars)
29-
figure_height_per_model = 0.8 # Figure height scaling factor per model
3032

3133
# Color parameters - each as list of (color, alpha) tuples
3234
# Plot 1: Grounding (logs, insights)
@@ -68,17 +70,16 @@ def __init__(self, df: pd.DataFrame):
6870
# Add hallucination category column
6971
self.df["hal_cat1"] = self.df.apply(self._get_l_reason_breakdown, axis=1)
7072

71-
# Sort models alphabetically by display name
73+
# Sort models alphabetically by display name (reversed)
7274
models = [m for m in df["model_name"].unique() if isinstance(m, str)]
7375
model_display_pairs = [(m, MODEL_TO_DISPLAY_NAME.get(m, m)) for m in models]
74-
model_display_pairs.sort(key=lambda x: x[1].lower())
76+
model_display_pairs.sort(key=lambda x: x[1].lower(), reverse=True)
7577
self.models = [m for m, _ in model_display_pairs]
7678
self.display_names = [d for _, d in model_display_pairs]
7779
self.n_models = len(self.models)
7880

7981
# Create figure with 3 subplots sharing y-axis
80-
fig_height = self.n_models * self.figure_height_per_model
81-
self.fig, self.axes = plt.subplots(1, 3, figsize=(13, fig_height), sharey=True)
82+
self.fig, self.axes = plt.subplots(1, 3, figsize=(12, 4), sharey=True)
8283
self.y_positions = np.arange(self.n_models)
8384

8485
def _get_l_reason_breakdown(self, row) -> str:
@@ -109,12 +110,13 @@ def _add_stacked_bar_labels(self, ax, stacked_values: list[list[float]], min_val
109110
x_pos = left[i] + val / 2
110111
# Determine text color based on segment index or value
111112
text_color = "white" if segment_idx < len(stacked_values) - 1 else "black"
113+
font_in_bar = FONT_BOLD.copy()
114+
font_in_bar.set_size(self.in_bar_number_fontsize)
112115
ax.text(
113116
x_pos,
114117
self.y_positions[i],
115118
f"{val:.0f}%",
116-
fontsize=self.in_bar_number_fontsize,
117-
fontweight=self.in_bar_number_fontweight,
119+
fontproperties=font_in_bar,
118120
ha="center",
119121
va="center",
120122
color=text_color,
@@ -131,12 +133,13 @@ def _add_total_bar_labels(self, ax, totals: list[float], x_offset: float = 1):
131133
"""
132134
for i, total in enumerate(totals):
133135
if total > 0:
136+
font_total = FONT_BOLD.copy()
137+
font_total.set_size(self.total_number_fontsize)
134138
ax.text(
135139
total + x_offset,
136140
self.y_positions[i],
137141
f"{total:.0f}%",
138-
fontsize=self.total_number_fontsize,
139-
fontweight=self.total_number_fontweight,
142+
fontproperties=font_total,
140143
ha="left",
141144
va="center",
142145
)
@@ -194,18 +197,39 @@ def plot_grounding_analysis(self):
194197
totals = [logs + insights for logs, insights in zip(motivated_by_logs, motivated_by_insights_not_logs)]
195198
self._add_total_bar_labels(ax, totals)
196199

197-
ax.set_title(
198-
"(a) Groundedness of edits",
199-
fontsize=self.title_fontsize,
200-
fontweight="bold",
201-
pad=self.title_pad,
200+
# Titles
201+
font_title = FONT_BOLD.copy()
202+
font_title.set_size(self.title_fontsize)
203+
ax.set_title("(a) Groundedness of edits", fontproperties=font_title, pad=self.title_pad)
204+
205+
# Legend
206+
font_legend = FONT_REG.copy()
207+
font_legend.set_size(self.legend_fontsize)
208+
leg = ax.legend(
209+
frameon=False,
210+
prop=font_legend,
211+
loc="upper center",
212+
bbox_to_anchor=(0.5, 1.25),
213+
borderaxespad=0.0,
202214
)
203-
ax.legend(loc="upper right", bbox_to_anchor=(1.2, 1), fontsize=self.legend_fontsize, frameon=False)
215+
leg.set_in_layout(False)
216+
217+
# Y-axis
204218
ax.set_yticks(self.y_positions)
205-
ax.set_yticklabels(self.display_names, fontsize=self.ytick_label_fontsize)
206-
ax.set_xlabel("Percentage of rounds", fontsize=self.label_fontsize)
219+
font_ytick = FONT_REG.copy()
220+
font_ytick.set_size(self.ytick_label_fontsize)
221+
ax.set_yticklabels(self.display_names, fontproperties=font_ytick)
222+
223+
# X-axis
224+
font_label = FONT_REG.copy()
225+
font_label.set_size(self.label_fontsize)
226+
ax.set_xlabel("Percentage of rounds", fontproperties=font_label)
207227
ax.tick_params(axis="y", length=0)
208228
ax.tick_params(axis="x", labelsize=self.xtick_label_fontsize)
229+
font_xtick = FONT_REG.copy()
230+
font_xtick.set_size(self.xtick_label_fontsize)
231+
for label in ax.get_xticklabels():
232+
label.set_fontproperties(font_xtick)
209233
ax.xaxis.set_minor_locator(plt.MultipleLocator(5))
210234
ax.spines["top"].set_visible(False)
211235
ax.spines["right"].set_visible(False)
@@ -252,7 +276,7 @@ def plot_validation_feedback(self):
252276
self.y_positions,
253277
tested_both,
254278
self.bar_height,
255-
label="Sim. + unittests",
279+
label="Sim + tests",
256280
alpha=alpha_both,
257281
color=color_both,
258282
)
@@ -261,7 +285,7 @@ def plot_validation_feedback(self):
261285
tested_unit_only,
262286
self.bar_height,
263287
left=tested_both,
264-
label="Unittests only",
288+
label="Tests",
265289
alpha=alpha_unit,
266290
color=color_unit,
267291
)
@@ -270,7 +294,7 @@ def plot_validation_feedback(self):
270294
tested_sim_only,
271295
self.bar_height,
272296
left=np.array(tested_both) + np.array(tested_unit_only),
273-
label="Simulations only",
297+
label="Sim.",
274298
alpha=alpha_sim,
275299
color=color_sim,
276300
)
@@ -280,16 +304,36 @@ def plot_validation_feedback(self):
280304
totals = [both + sim + unit for both, sim, unit in zip(tested_both, tested_sim_only, tested_unit_only)]
281305
self._add_total_bar_labels(ax, totals)
282306

283-
ax.set_title(
284-
"(c) Validation of edits",
285-
fontsize=self.title_fontsize,
286-
fontweight="bold",
287-
pad=self.title_pad,
307+
# Titles
308+
font_title = FONT_BOLD.copy()
309+
font_title.set_size(self.title_fontsize)
310+
ax.set_title("(c) Validation of edits", fontproperties=font_title, pad=self.title_pad)
311+
312+
# Legend
313+
font_legend = FONT_REG.copy()
314+
font_legend.set_size(self.legend_fontsize)
315+
leg = ax.legend(
316+
frameon=False,
317+
prop=font_legend,
318+
loc="upper center",
319+
bbox_to_anchor=(0.5, 1.25),
320+
borderaxespad=0.0,
321+
ncol=2,
322+
columnspacing=0.6,
323+
handletextpad=0.4,
288324
)
289-
ax.legend(loc="upper right", bbox_to_anchor=(1.15, 1), fontsize=self.legend_fontsize, frameon=False)
290-
ax.set_xlabel("Percentage of rounds", fontsize=self.label_fontsize)
325+
leg.set_in_layout(False)
326+
327+
# X-axis
328+
font_label = FONT_REG.copy()
329+
font_label.set_size(self.label_fontsize)
330+
ax.set_xlabel("Percentage of rounds", fontproperties=font_label)
291331
ax.tick_params(axis="y", length=0)
292332
ax.tick_params(axis="x", labelsize=self.xtick_label_fontsize)
333+
font_xtick = FONT_REG.copy()
334+
font_xtick.set_size(self.xtick_label_fontsize)
335+
for label in ax.get_xticklabels():
336+
label.set_fontproperties(font_xtick)
293337
ax.xaxis.set_minor_locator(plt.MultipleLocator(5))
294338
ax.spines["top"].set_visible(False)
295339
ax.spines["right"].set_visible(False)
@@ -298,66 +342,82 @@ def plot_hallucination_categories(self):
298342
"""Plot: Hallucinated/Unproven Loss Causality Claims."""
299343
ax = self.axes[1]
300344

301-
category_order = ["logs/analysis", "docs/tests/other", "no source"]
302-
303-
# Collect data for each model
304-
model_data = []
345+
# Combine categories into two: misinterpretation (logs/analysis + docs/tests/other) and no source
346+
misinterpretation = []
347+
no_source = []
305348
for model in self.models:
306349
model_df = self.df[self.df["model_name"] == model]
307350
total_rounds = len(model_df)
308-
category_values = []
309351

310-
for category in category_order:
311-
count = (model_df["hal_cat1"] == category).sum()
312-
pct = (count / total_rounds * 100) if total_rounds > 0 else 0
313-
category_values.append(pct)
352+
mis_count = ((model_df["hal_cat1"] == "logs/analysis") | (model_df["hal_cat1"] == "docs/tests/other")).sum()
353+
no_src_count = (model_df["hal_cat1"] == "no source").sum()
314354

315-
model_data.append(category_values)
355+
misinterpretation.append((mis_count / total_rounds * 100) if total_rounds > 0 else 0)
356+
no_source.append((no_src_count / total_rounds * 100) if total_rounds > 0 else 0)
316357

317358
# Plot stacked bars
318359
left = np.zeros(self.n_models)
319360

320-
for cat_idx, category in enumerate(category_order):
321-
values = [model_data[model_idx][cat_idx] for model_idx in range(self.n_models)]
322-
color, alpha = self.hallucination_colors[cat_idx]
323-
324-
ax.barh(
325-
self.y_positions,
326-
values,
327-
self.bar_height,
328-
left=left,
329-
label=category,
330-
alpha=alpha,
331-
color=color,
332-
)
333-
left = left + np.array(values)
361+
# Colors: use first for misinterpretation, third for no source
362+
color_mis, alpha_mis = self.hallucination_colors[0]
363+
color_no, alpha_no = self.hallucination_colors[2]
364+
365+
ax.barh(
366+
self.y_positions,
367+
misinterpretation,
368+
self.bar_height,
369+
left=left,
370+
label="Misinterpreted source",
371+
alpha=alpha_mis,
372+
color=color_mis,
373+
)
374+
left = left + np.array(misinterpretation)
375+
ax.barh(
376+
self.y_positions,
377+
no_source,
378+
self.bar_height,
379+
left=left,
380+
label="No source",
381+
alpha=alpha_no,
382+
color=color_no,
383+
)
334384

335385
# Add labels
336-
stacked_values = [
337-
[model_data[model_idx][cat_idx] for model_idx in range(self.n_models)]
338-
for cat_idx in range(len(category_order))
339-
]
386+
stacked_values = [misinterpretation, no_source]
340387
self._add_stacked_bar_labels(ax, stacked_values, min_value_to_show=3.0)
341-
totals = [sum(model_data[i]) for i in range(self.n_models)]
388+
totals = [misinterpretation[i] + no_source[i] for i in range(self.n_models)]
342389
self._add_total_bar_labels(ax, totals)
343390

344-
ax.set_title(
345-
"(b) Hallucinated Loss Causality",
346-
fontsize=self.title_fontsize,
347-
fontweight="bold",
348-
pad=self.title_pad,
349-
)
350-
ax.legend(
351-
loc="center right",
352-
bbox_to_anchor=(1.15, 0.55),
353-
fontsize=self.legend_fontsize,
391+
# Titles
392+
font_title = FONT_BOLD.copy()
393+
font_title.set_size(self.title_fontsize)
394+
ax.set_title("(b) Hallucinated Loss Causality", fontproperties=font_title, pad=self.title_pad)
395+
396+
# Legend
397+
font_legend = FONT_REG.copy()
398+
font_legend.set_size(self.legend_fontsize)
399+
leg = ax.legend(
354400
frameon=False,
355-
title="Hallucinated claims based on",
356-
title_fontsize=12,
401+
prop=font_legend,
402+
loc="upper center",
403+
bbox_to_anchor=(0.5, 1.25),
404+
borderaxespad=0.0,
405+
ncol=1,
406+
columnspacing=0.6,
407+
handletextpad=0.4,
357408
)
358-
ax.set_xlabel("Percentage of rounds", fontsize=self.label_fontsize)
409+
leg.set_in_layout(False)
410+
411+
# X-axis
412+
font_label = FONT_REG.copy()
413+
font_label.set_size(self.label_fontsize)
414+
ax.set_xlabel("Percentage of rounds", fontproperties=font_label)
359415
ax.tick_params(axis="y", length=0)
360416
ax.tick_params(axis="x", labelsize=self.xtick_label_fontsize)
417+
font_xtick = FONT_REG.copy()
418+
font_xtick.set_size(self.xtick_label_fontsize)
419+
for label in ax.get_xticklabels():
420+
label.set_fontproperties(font_xtick)
361421
ax.xaxis.set_minor_locator(plt.MultipleLocator(5))
362422
ax.spines["top"].set_visible(False)
363423
ax.spines["right"].set_visible(False)

0 commit comments

Comments
 (0)