Skip to content

Commit 92e4261

Browse files
authored
Merge pull request #3 from lamalab-org/copilot/make-axes-more-intuitive
Add "↑/↓ better" direction annotations to all metric y-axes
2 parents 1e1b271 + 8a5b7cb commit 92e4261

1 file changed

Lines changed: 40 additions & 0 deletions

File tree

src/scripts/plotting_utils.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,31 @@
5757
'recall_macro': 'Recall (Macro)'
5858
}
5959

60+
# Metrics where lower values are better
61+
_LOWER_IS_BETTER_METRICS = {'mae', 'mape', 'rmse', 'mse'}
62+
63+
64+
def _is_lower_better(metric: str) -> bool:
65+
"""Return True if lower values are better for this metric."""
66+
return metric.lower() in _LOWER_IS_BETTER_METRICS
67+
68+
69+
def _add_good_direction_annotation(ax: plt.Axes, metric: str, compact: bool = False) -> None:
70+
"""Add a small annotation near the y-axis indicating the direction of improvement.
71+
72+
Plots '↓ better' for error metrics (MAE, MAPE) where lower is better,
73+
and '↑ better' for score metrics (F1, Accuracy, R²) where higher is better.
74+
"""
75+
arrow = '↓' if _is_lower_better(metric) else '↑'
76+
fontsize = 6 if compact else 7
77+
ax.text(
78+
0, 1.02, f'{arrow} better',
79+
transform=ax.transAxes,
80+
fontsize=fontsize,
81+
ha='left', va='bottom',
82+
color='gray', fontstyle='italic',
83+
)
84+
6085

6186
def plot_performance_comparison(results: Dict[str, Any],
6287
target_type: str = 'regression',
@@ -133,6 +158,9 @@ def plot_performance_comparison(results: Dict[str, Any],
133158
ax.set_ylabel(metric_label, fontsize=10, labelpad=15)
134159
ax.yaxis.set_label_coords(-0.45, 0.5) # Fixed position with better padding
135160

161+
# Indicate which direction is better
162+
_add_good_direction_annotation(ax, metric)
163+
136164
# Apply range frame
137165
if len(valid_means) > 0:
138166
range_frame(ax, x_positions, valid_means)
@@ -445,6 +473,9 @@ def plot_parameter_sweep_results(sweep_results: List[Dict[str, Any]],
445473
ax.legend(fontsize=8)
446474
ax.set_xscale('log')
447475

476+
# Indicate which direction is better
477+
_add_good_direction_annotation(ax, metric)
478+
448479
# Apply range frame
449480
if all_x and all_y:
450481
range_frame(ax, np.array(all_x), np.array(all_y))
@@ -594,6 +625,9 @@ def _plot_meta_prediction_panel(ax, results: Dict[str, Any], meta_type: str,
594625
else:
595626
ax.set_ylabel(ylabel_text, fontsize=fontsize_tick+1, labelpad=10)
596627

628+
# Indicate which direction is better
629+
_add_good_direction_annotation(ax, metric, compact=compact)
630+
597631
ax.set_xticks(x_pos)
598632
ax.set_xticklabels(labels_list, rotation=30, ha='right', fontsize=fontsize_tick)
599633

@@ -746,6 +780,9 @@ def create_main_figure_panel(results: Dict[str, Any],
746780
# Use manual ylabel for better control
747781
ax_perf.set_ylabel(metric_label, fontsize=10, labelpad=12)
748782

783+
# Indicate which direction is better
784+
_add_good_direction_annotation(ax_perf, main_metric)
785+
749786
# Add panel label D
750787
ax_perf.text(-0.03, 1.05, 'D', transform=ax_perf.transAxes,
751788
fontsize=12, fontweight='bold', ha='center')
@@ -974,6 +1011,9 @@ def plot_meta_comparison(comparison_results: Dict[str, Any],
9741011
metric_label = metric_labels.get(primary_metric, primary_metric.upper()) if metric_labels else primary_metric.upper()
9751012
ax_property.set_ylabel(metric_label)
9761013

1014+
# Indicate which direction is better
1015+
_add_good_direction_annotation(ax_property, primary_metric)
1016+
9771017
# Add baseline reference if applicable
9781018
if not np.isnan(means[1]): # dummy baseline
9791019
range_frame(ax_property, np.array([0]), np.array([means[1]]))

0 commit comments

Comments
 (0)