Skip to content

Commit 9ce669b

Browse files
ph-kevSbozzolo
authored andcommitted
Fix legend covering parts of box plot
The legend could overflow onto the box plot when the model names are too long. To prevent this, an additional parameter called `legend_text_width` is added which control the number of characters on each line.
1 parent bf4c94d commit 9ce669b

File tree

3 files changed

+76
-13
lines changed

3 files changed

+76
-13
lines changed

NEWS.md

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ julia> reordered_var.dims |> keys |> collect
3535

3636
- Fix models repeating in legend of box plots by not considering the models in `model_names`
3737
when finding the best and worst models
38+
- Fix legend from covering the box plot by adding the parameter `legend_text_width` which
39+
control the number of characters on each line of the legend of the box plot
3840

3941
v0.5.8
4042
------

ext/ClimaAnalysisMakieExt.jl

+32-12
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,8 @@ end
635635
rmse_var::ClimaAnalysis.RMSEVariable;
636636
model_names = ["CliMA"],
637637
ploc = (1, 1),
638-
best_and_worst_category_name = "ANN")
638+
best_and_worst_category_name = "ANN",
639+
legend_text_width = 10)
639640
640641
Plot a Tukey style boxplot for each category in `rmse_var`.
641642
@@ -644,14 +645,16 @@ and are plotted on the boxplot. When finding the best and worst single models, a
644645
`model_names` will be excluded. Additionally, any model in `model_names` will also be
645646
plotted on the boxplot.
646647
647-
The parameter `ploc` determines where to place the plot on the figure.
648+
The parameter `ploc` determines where to place the plot on the figure. The parameter
649+
`legend_text_width` determines the number of characters on each line in the legend.
648650
"""
649651
function Visualize.plot_boxplot!(
650652
fig,
651653
rmse_var::ClimaAnalysis.RMSEVariable;
652654
model_names = ["CliMA"],
653655
ploc = (1, 1),
654656
best_and_worst_category_name = "ANN",
657+
legend_text_width = 10,
655658
)
656659
# Unit checking
657660
ClimaAnalysis.Leaderboard._unit_check(rmse_var)
@@ -709,21 +712,21 @@ function Visualize.plot_boxplot!(
709712
rmse_var_delete,
710713
category_name = best_and_worst_category_name,
711714
)
712-
Makie.scatter!(
715+
best_pt = Makie.scatter!(
713716
ax,
714717
1:num_cats,
715-
absolute_worst_values,
716-
label = absolute_worst_model_name,
718+
absolute_best_values,
719+
label = absolute_best_model_name,
717720
)
718-
Makie.scatter!(
721+
worst_pt = Makie.scatter!(
719722
ax,
720723
1:num_cats,
721-
absolute_best_values,
722-
label = absolute_best_model_name,
724+
absolute_worst_values,
725+
label = absolute_worst_model_name,
723726
)
724727

725728
# Plotting the median model
726-
Makie.scatter!(
729+
median_pt = Makie.scatter!(
727730
ax,
728731
1:num_cats,
729732
ClimaAnalysis.median(rmse_var),
@@ -734,6 +737,13 @@ function Visualize.plot_boxplot!(
734737
visible = false,
735738
)
736739

740+
# Keep track of points plotted by scatter! and names for plotting the legend
741+
# later
742+
pts_on_boxplot = [median_pt, best_pt, worst_pt]
743+
names_on_legend = vcat(
744+
["Median", absolute_best_model_name, absolute_worst_model_name],
745+
model_names,
746+
)
737747
# Plot CliMA model and other models
738748
for model_name in model_names
739749
ClimaAnalysis.Leaderboard._model_name_check(rmse_var, model_name)
@@ -746,7 +756,7 @@ function Visualize.plot_boxplot!(
746756
marker = :star5,
747757
markersize = 20,
748758
color = :green,
749-
)
759+
) |> pt -> push!(pts_on_boxplot, pt)
750760
else
751761
Makie.scatter!(
752762
ax,
@@ -755,12 +765,22 @@ function Visualize.plot_boxplot!(
755765
label = model_name,
756766
markersize = 20,
757767
color = :red,
758-
)
768+
) |> pt -> push!(pts_on_boxplot, pt)
759769
end
760770
end
761771

772+
# Add a new line character every `legend_text_width` characters to prevent legend from
773+
# overflowing onto the box plot
774+
# Soln from
775+
# https://stackoverflow.com/questions/40545980/insert-a-newline-character-every-10-characters-in-a-string-using-julia
776+
names_on_legend = map(
777+
name ->
778+
replace(name, Regex("(.{$legend_text_width})") => s"\1\n") |>
779+
(name -> rstrip(name, '\n')),
780+
names_on_legend,
781+
)
762782
# Hack to make legend appear better
763-
Makie.axislegend()
783+
Makie.axislegend(ax, pts_on_boxplot, names_on_legend)
764784
Makie.scatter!(ax, [num_cats + 2.5], [0.1], markersize = 0.01)
765785
end
766786

test/test_MakieExt.jl

+42-1
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,22 @@ using OrderedCollections
191191
),
192192
)
193193
rmse_var[2, 5] = 4.0
194+
195+
rmse_var1 = ClimaAnalysis.read_rmses(csv_file_path, "ta")
196+
rmse_var1 = ClimaAnalysis.add_model(rmse_var1, "CliMA", "test_model")
197+
rmse_var1["CliMA", :] = [12.0, 12.0, 11.0, 14.0, 6.0]
198+
rmse_var1["test_model", :] = [12.0, 12.0, 11.0, 14.0, 6.0]
199+
ClimaAnalysis.add_unit!(
200+
rmse_var1,
201+
Dict(
202+
"ACCESS-ESM1-5" => "units",
203+
"ACCESS-CM2" => "units",
204+
"CliMA" => "units",
205+
"test_model" => "units",
206+
),
207+
)
208+
rmse_var1[2, 5] = 4.0
209+
194210
fig = Makie.Figure(; size = (800, 300 * 3 + 400), fontsize = 20)
195211
ClimaAnalysis.Visualize.plot_boxplot!(
196212
fig,
@@ -207,7 +223,7 @@ using OrderedCollections
207223
)
208224
ClimaAnalysis.Visualize.plot_boxplot!(
209225
fig,
210-
rmse_var,
226+
rmse_var1,
211227
model_names = ["CliMA", "ACCESS-ESM1-5"],
212228
ploc = (3, 1),
213229
best_and_worst_category_name = "ANN",
@@ -333,6 +349,31 @@ using OrderedCollections
333349
output_name = joinpath(tmp_dir, "test_leaderboard_nan.png")
334350
Makie.save(output_name, fig)
335351

352+
# Testing with long name
353+
rmse_var = ClimaAnalysis.read_rmses(csv_file_path, "ta")
354+
rmse_var = ClimaAnalysis.add_model(
355+
rmse_var,
356+
"long_name_name_name_name_name_name_name",
357+
)
358+
ClimaAnalysis.add_unit!(
359+
rmse_var,
360+
Dict(
361+
"ACCESS-ESM1-5" => "units",
362+
"ACCESS-CM2" => "units",
363+
"long_name_name_name_name_name_name_name" => "units",
364+
),
365+
)
366+
rmse_var[2, 5] = 10.0
367+
fig = Makie.Figure(; fontsize = 20)
368+
ClimaAnalysis.Visualize.plot_boxplot!(
369+
fig,
370+
rmse_var,
371+
model_names = ["long_name_name_name_name_name_name_name"],
372+
best_and_worst_category_name = "ANN",
373+
)
374+
output_name = joinpath(tmp_dir, "test_boxplot_long_name.png")
375+
Makie.save(output_name, fig)
376+
336377
# Test error handling for plot_leaderboard
337378
csv_file_path = joinpath(@__DIR__, "sample_data/test_csv.csv")
338379
rmse_var1 = ClimaAnalysis.read_rmses(csv_file_path, "ta")

0 commit comments

Comments
 (0)