From 4b3be1fddd3799f6f88ed498576cd9cc5e0d983b Mon Sep 17 00:00:00 2001 From: Tarn Yeong Ching Date: Tue, 11 Jul 2023 11:35:51 +0800 Subject: [PATCH 1/6] fix grouping of zero-height bar in `barplot` --- src/basic_recipes/barplot.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/basic_recipes/barplot.jl b/src/basic_recipes/barplot.jl index b62164c1f15..c744ea3bd92 100644 --- a/src/basic_recipes/barplot.jl +++ b/src/basic_recipes/barplot.jl @@ -110,7 +110,11 @@ function stack_grouped_from_to(i_stack, y, grp) from = Array{Float64}(undef, length(y)) to = Array{Float64}(undef, length(y)) - groupby = StructArray((; grp..., is_pos = y .> 0)) + last_pos = any(y .> 0) + is_pos = map(y) do v + last_pos = iszero(v) ? last_pos : v > 0 + end + groupby = StructArray((; grp..., is_pos)) grps = StructArrays.finduniquesorted(groupby) From 5c1258249bddadb581ccd3612d64b4953e359440 Mon Sep 17 00:00:00 2001 From: Tarn Yeong Ching Date: Tue, 11 Jul 2023 12:09:41 +0800 Subject: [PATCH 2/6] treat all-zero as positive --- src/basic_recipes/barplot.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic_recipes/barplot.jl b/src/basic_recipes/barplot.jl index c744ea3bd92..8bdaddb8bbf 100644 --- a/src/basic_recipes/barplot.jl +++ b/src/basic_recipes/barplot.jl @@ -110,7 +110,7 @@ function stack_grouped_from_to(i_stack, y, grp) from = Array{Float64}(undef, length(y)) to = Array{Float64}(undef, length(y)) - last_pos = any(y .> 0) + last_pos = any(y .> 0) || all(y .== 0) is_pos = map(y) do v last_pos = iszero(v) ? last_pos : v > 0 end From d9bdd7965d76818d66eb4b8b758370a1ffdec395 Mon Sep 17 00:00:00 2001 From: Tarn Yeong Ching Date: Thu, 24 Aug 2023 16:51:45 +0800 Subject: [PATCH 3/6] store `last_pos` of each group --- src/basic_recipes/barplot.jl | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/basic_recipes/barplot.jl b/src/basic_recipes/barplot.jl index 6fe405e8643..743d556cd73 100644 --- a/src/basic_recipes/barplot.jl +++ b/src/basic_recipes/barplot.jl @@ -140,25 +140,24 @@ function stack_from_to(i_stack, y) end function stack_grouped_from_to(i_stack, y, grp) - from = Array{Float64}(undef, length(y)) to = Array{Float64}(undef, length(y)) - last_pos = any(y .> 0) || all(y .== 0) - is_pos = map(y) do v - last_pos = iszero(v) ? last_pos : v > 0 + groupby = StructArray((; grp...)) + grps = StructArrays.finduniquesorted(groupby) + last_pos = map(grps) do (g, inds) + g => any(y[inds] .> 0) || all(y[inds] .== 0) + end |> Dict + is_pos = map(y, groupby) do v, g + last_pos[g] = iszero(v) ? last_pos[g] : v > 0 end - groupby = StructArray((; grp..., is_pos)) + groupby = StructArray((; grp..., is_pos)) grps = StructArrays.finduniquesorted(groupby) - for (grp, inds) in grps - fromto = stack_from_to(i_stack[inds], y[inds]) - from[inds] .= fromto.from to[inds] .= fromto.to - end (from = from, to = to) From d62f997bbf4a0d1070f2de31b6ed3fdea313a29e Mon Sep 17 00:00:00 2001 From: Tarn Yeong Ching Date: Sat, 30 Sep 2023 23:12:11 +0800 Subject: [PATCH 4/6] add #3058 to NEWS --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index ba9f8b394c4..afa2e0c0ba0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ # News ## master +- Fix grouping of a zero-height bar in `barplot`. Now a zero-height bar shares the same properties of the previous bar, and if the bar is the first one, its height is treated as positive if and only if there exists a bar of positive height or all bars are zero-height. [#3058](https://github.com/MakieOrg/Makie.jl/pull/3058) ## v0.19.10 From 885880b9e6d94375227ac0663895b13617fd9c04 Mon Sep 17 00:00:00 2001 From: Tarn Yeong Ching Date: Sun, 1 Oct 2023 00:29:12 +0800 Subject: [PATCH 5/6] test: add zero-height bar --- test/stack.jl | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/stack.jl b/test/stack.jl index e03b5779a8b..729aa93a274 100644 --- a/test/stack.jl +++ b/test/stack.jl @@ -36,3 +36,43 @@ using Makie: stack_grouped_from_to @test from == from_test @test to == to_test end + +@testset "grouped bar: zero-height" begin + grp_stack = [1, 2, 1, 2] + x = [1, 1, 2, 2] + + y = [1.0, 0.0, -1.0, -1.0] + from = [0.0, 1.0, 0.0, -1.0] + to = [1.0, 1.0, -1.0, -2.0] + from_, to_ = stack_grouped_from_to(grp_stack, y, (; x)) + @test from == from_ + @test to == to_ + + y = [-1.0, 0.0, -1.0, -1.0] + from = [0.0, -1.0, 0.0, -1.0] + to = [-1.0, -1.0, -1.0, -2.0] + from_, to_ = stack_grouped_from_to(grp_stack, y, (; x)) + @test from == from_ + @test to == to_ + + y = [0.0, 1.0, -1.0, -1.0] + from = [0.0, 0.0, 0.0, -1.0] + to = [0.0, 1.0, -1.0, -2.0] + from_, to_ = stack_grouped_from_to(grp_stack, y, (; x)) + @test from == from_ + @test to == to_ + + y = [0.0, -1.0, -1.0, -1.0] + from = [0.0, 0.0, 0.0, -1.0] + to = [0.0, -1.0, -1.0, -2.0] + from_, to_ = stack_grouped_from_to(grp_stack, y, (; x)) + @test from == from_ + @test to == to_ + + y = [0.0, 1.0, -1.0, -1.0] + from = [0.0, 0.0, 0.0, -1.0] + to = [0.0, 1.0, -1.0, -2.0] + from_, to_ = stack_grouped_from_to(1:4, y, (; x=ones(4))) + @test from == from_ + @test to == to_ +end From db5861cdefd445ece2fde2d4a693969851069911 Mon Sep 17 00:00:00 2001 From: Tarn Yeong Ching Date: Sun, 1 Oct 2023 00:39:43 +0800 Subject: [PATCH 6/6] test: merge barplot-related tests into `barplot` --- test/barplot.jl | 130 +++++++++++++++++++++++++++++++++++++++++ test/barplot_labels.jl | 52 ----------------- test/runtests.jl | 3 +- test/stack.jl | 78 ------------------------- 4 files changed, 131 insertions(+), 132 deletions(-) create mode 100644 test/barplot.jl delete mode 100644 test/barplot_labels.jl delete mode 100644 test/stack.jl diff --git a/test/barplot.jl b/test/barplot.jl new file mode 100644 index 00000000000..2a1e6bf9a79 --- /dev/null +++ b/test/barplot.jl @@ -0,0 +1,130 @@ +@testset "Barplot" begin + @testset "label align" begin + @testset "automatic" begin + # for more info see https://github.com/MakieOrg/Makie.jl/issues/3160 + # below is the best square angles behavior for bar labels + + al = Makie.automatic + + y_dir, flip = false, false + @test Makie.calculate_bar_label_align(al, 0.0, y_dir, flip) ≈ Vec2f(0.0, 0.5) + @test Makie.calculate_bar_label_align(al, π, y_dir, flip) ≈ Vec2f(1.0, 0.5) + @test Makie.calculate_bar_label_align(al, π/2, y_dir, flip) ≈ Vec2f(0.5, 1.0) + @test Makie.calculate_bar_label_align(al, -π/2, y_dir, flip) ≈ Vec2f(0.5, 0.0) + + y_dir, flip = true, false + @test Makie.calculate_bar_label_align(al, 0.0, y_dir, flip) ≈ Vec2f(0.5, 0.0) + @test Makie.calculate_bar_label_align(al, π, y_dir, flip) ≈ Vec2f(0.5, 1.0) + @test Makie.calculate_bar_label_align(al, π/2, y_dir, flip) ≈ Vec2f(0.0, 0.5) + @test Makie.calculate_bar_label_align(al, -π/2, y_dir, flip) ≈ Vec2f(1.0, 0.5) + + y_dir, flip = false, true + @test Makie.calculate_bar_label_align(al, 0.0, y_dir, flip) ≈ Vec2f(1.0, 0.5) + @test Makie.calculate_bar_label_align(al, π, y_dir, flip) ≈ Vec2f(0.0, 0.5) + @test Makie.calculate_bar_label_align(al, π/2, y_dir, flip) ≈ Vec2f(0.5, 0.0) + @test Makie.calculate_bar_label_align(al, -π/2, y_dir, flip) ≈ Vec2f(0.5, 1.0) + + y_dir, flip = true, true + @test Makie.calculate_bar_label_align(al, 0.0, y_dir, flip) ≈ Vec2f(0.5, 1.0) + @test Makie.calculate_bar_label_align(al, π, y_dir, flip) ≈ Vec2f(0.5, 0.0) + @test Makie.calculate_bar_label_align(al, π/2, y_dir, flip) ≈ Vec2f(1.0, 0.5) + @test Makie.calculate_bar_label_align(al, -π/2, y_dir, flip) ≈ Vec2f(0.0, 0.5) + end + + @testset "manual" begin + input = 0.0, false, false + for align in (Vec2f(1.0, 0.5), Point2f(1.0, 0.5), (1.0, 0.5), (1, 0), (1.0, 0)) + @test Makie.calculate_bar_label_align(align, input...) ≈ Vec2f(align) + end + end + + @testset "symbols" begin + input = 0.0, false, false + @test Makie.calculate_bar_label_align((:center, :center), input...) ≈ Makie.calculate_bar_label_align((0.5, 0.5), input...) + end + + @testset "error" begin + input = 0.0, false, false + for align in ("center", 0.5, ("center", "center")) + @test_throws ErrorException Makie.calculate_bar_label_align(align, input...) + end + end + end + + @testset "stack" begin + x1 = [1, 1, 1, 1] + grp_dodge1 = [2, 2, 1, 1] + grp_stack1 = [1, 2, 1, 2] + y1 = [2, 3, -3, -2] + + x2 = [2, 2, 2, 2] + grp_dodge2 = [3, 4, 3, 4] + grp_stack2 = [3, 4, 3, 4] + y2 = [2, 3, -3, -2] + + from, to = Makie.stack_grouped_from_to(grp_stack1, y1, (; x1 = x1, grp_dodge1 = grp_dodge1)) + from1 = [0.0, 2.0, 0.0, -3.0] + to1 = [2.0, 5.0, -3.0, -5.0] + @test from == from1 + @test to == to1 + + from, to = Makie.stack_grouped_from_to(grp_stack2, y2, (; x2 = x2, grp_dodge2 = grp_dodge2)) + from2 = [0.0, 0.0, 0.0, 0.0] + to2 = [2.0, 3.0, -3.0, -2.0] + @test from == from2 + @test to == to2 + + perm = [1, 4, 2, 7, 5, 3, 8, 6] + x = [x1; x2][perm] + y = [y1; y2][perm] + grp_dodge = [grp_dodge1; grp_dodge2][perm] + grp_stack = [grp_stack1; grp_stack2][perm] + + from_test = [from1; from2][perm] + to_test = [to1; to2][perm] + + from, to = Makie.stack_grouped_from_to(grp_stack, y, (; x = x, grp_dodge = grp_dodge)) + @test from == from_test + @test to == to_test + end + + @testset "zero-height" begin + grp_stack = [1, 2, 1, 2] + x = [1, 1, 2, 2] + + y = [1.0, 0.0, -1.0, -1.0] + from = [0.0, 1.0, 0.0, -1.0] + to = [1.0, 1.0, -1.0, -2.0] + from_, to_ = Makie.stack_grouped_from_to(grp_stack, y, (; x)) + @test from == from_ + @test to == to_ + + y = [-1.0, 0.0, -1.0, -1.0] + from = [0.0, -1.0, 0.0, -1.0] + to = [-1.0, -1.0, -1.0, -2.0] + from_, to_ = Makie.stack_grouped_from_to(grp_stack, y, (; x)) + @test from == from_ + @test to == to_ + + y = [0.0, 1.0, -1.0, -1.0] + from = [0.0, 0.0, 0.0, -1.0] + to = [0.0, 1.0, -1.0, -2.0] + from_, to_ = Makie.stack_grouped_from_to(grp_stack, y, (; x)) + @test from == from_ + @test to == to_ + + y = [0.0, -1.0, -1.0, -1.0] + from = [0.0, 0.0, 0.0, -1.0] + to = [0.0, -1.0, -1.0, -2.0] + from_, to_ = Makie.stack_grouped_from_to(grp_stack, y, (; x)) + @test from == from_ + @test to == to_ + + y = [0.0, 1.0, -1.0, -1.0] + from = [0.0, 0.0, 0.0, -1.0] + to = [0.0, 1.0, -1.0, -2.0] + from_, to_ = Makie.stack_grouped_from_to(1:4, y, (; x=ones(4))) + @test from == from_ + @test to == to_ + end +end diff --git a/test/barplot_labels.jl b/test/barplot_labels.jl deleted file mode 100644 index f99bcf1347e..00000000000 --- a/test/barplot_labels.jl +++ /dev/null @@ -1,52 +0,0 @@ -@testset "Barplot label align" begin - @testset "automatic" begin - # for more info see https://github.com/MakieOrg/Makie.jl/issues/3160 - # below is the best square angles behavior for bar labels - - al = Makie.automatic - - y_dir, flip = false, false - @test Makie.calculate_bar_label_align(al, 0.0, y_dir, flip) ≈ Vec2f(0.0, 0.5) - @test Makie.calculate_bar_label_align(al, π, y_dir, flip) ≈ Vec2f(1.0, 0.5) - @test Makie.calculate_bar_label_align(al, π/2, y_dir, flip) ≈ Vec2f(0.5, 1.0) - @test Makie.calculate_bar_label_align(al, -π/2, y_dir, flip) ≈ Vec2f(0.5, 0.0) - - y_dir, flip = true, false - @test Makie.calculate_bar_label_align(al, 0.0, y_dir, flip) ≈ Vec2f(0.5, 0.0) - @test Makie.calculate_bar_label_align(al, π, y_dir, flip) ≈ Vec2f(0.5, 1.0) - @test Makie.calculate_bar_label_align(al, π/2, y_dir, flip) ≈ Vec2f(0.0, 0.5) - @test Makie.calculate_bar_label_align(al, -π/2, y_dir, flip) ≈ Vec2f(1.0, 0.5) - - y_dir, flip = false, true - @test Makie.calculate_bar_label_align(al, 0.0, y_dir, flip) ≈ Vec2f(1.0, 0.5) - @test Makie.calculate_bar_label_align(al, π, y_dir, flip) ≈ Vec2f(0.0, 0.5) - @test Makie.calculate_bar_label_align(al, π/2, y_dir, flip) ≈ Vec2f(0.5, 0.0) - @test Makie.calculate_bar_label_align(al, -π/2, y_dir, flip) ≈ Vec2f(0.5, 1.0) - - y_dir, flip = true, true - @test Makie.calculate_bar_label_align(al, 0.0, y_dir, flip) ≈ Vec2f(0.5, 1.0) - @test Makie.calculate_bar_label_align(al, π, y_dir, flip) ≈ Vec2f(0.5, 0.0) - @test Makie.calculate_bar_label_align(al, π/2, y_dir, flip) ≈ Vec2f(1.0, 0.5) - @test Makie.calculate_bar_label_align(al, -π/2, y_dir, flip) ≈ Vec2f(0.0, 0.5) - end - - @testset "manual" begin - input = 0.0, false, false - for align in (Vec2f(1.0, 0.5), Point2f(1.0, 0.5), (1.0, 0.5), (1, 0), (1.0, 0)) - @test Makie.calculate_bar_label_align(align, input...) ≈ Vec2f(align) - end - end - - @testset "symbols" begin - input = 0.0, false, false - @test Makie.calculate_bar_label_align((:center, :center), input...) ≈ Makie.calculate_bar_label_align((0.5, 0.5), input...) - end - - @testset "error" begin - input = 0.0, false, false - for align in ("center", 0.5, ("center", "center")) - @test_throws ErrorException Makie.calculate_bar_label_align(align, input...) - end - end - -end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 3ade28d3d1b..b990453c009 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -28,11 +28,10 @@ using Makie: volume include("makielayout.jl") include("figures.jl") include("transformations.jl") - include("stack.jl") include("events.jl") include("text.jl") include("boundingboxes.jl") include("ray_casting.jl") include("PolarAxis.jl") - include("barplot_labels.jl") + include("barplot.jl") end diff --git a/test/stack.jl b/test/stack.jl deleted file mode 100644 index 729aa93a274..00000000000 --- a/test/stack.jl +++ /dev/null @@ -1,78 +0,0 @@ -using Makie: stack_grouped_from_to - -@testset "grouped bar: stack" begin - x1 = [1, 1, 1, 1] - grp_dodge1 = [2, 2, 1, 1] - grp_stack1 = [1, 2, 1, 2] - y1 = [2, 3, -3, -2] - - x2 = [2, 2, 2, 2] - grp_dodge2 = [3, 4, 3, 4] - grp_stack2 = [3, 4, 3, 4] - y2 = [2, 3, -3, -2] - - from, to = stack_grouped_from_to(grp_stack1, y1, (; x1 = x1, grp_dodge1 = grp_dodge1)) - from1 = [0.0, 2.0, 0.0, -3.0] - to1 = [2.0, 5.0, -3.0, -5.0] - @test from == from1 - @test to == to1 - - from, to = stack_grouped_from_to(grp_stack2, y2, (; x2 = x2, grp_dodge2 = grp_dodge2)) - from2 = [0.0, 0.0, 0.0, 0.0] - to2 = [2.0, 3.0, -3.0, -2.0] - @test from == from2 - @test to == to2 - - perm = [1, 4, 2, 7, 5, 3, 8, 6] - x = [x1; x2][perm] - y = [y1; y2][perm] - grp_dodge = [grp_dodge1; grp_dodge2][perm] - grp_stack = [grp_stack1; grp_stack2][perm] - - from_test = [from1; from2][perm] - to_test = [to1; to2][perm] - - from, to = stack_grouped_from_to(grp_stack, y, (; x = x, grp_dodge = grp_dodge)) - @test from == from_test - @test to == to_test -end - -@testset "grouped bar: zero-height" begin - grp_stack = [1, 2, 1, 2] - x = [1, 1, 2, 2] - - y = [1.0, 0.0, -1.0, -1.0] - from = [0.0, 1.0, 0.0, -1.0] - to = [1.0, 1.0, -1.0, -2.0] - from_, to_ = stack_grouped_from_to(grp_stack, y, (; x)) - @test from == from_ - @test to == to_ - - y = [-1.0, 0.0, -1.0, -1.0] - from = [0.0, -1.0, 0.0, -1.0] - to = [-1.0, -1.0, -1.0, -2.0] - from_, to_ = stack_grouped_from_to(grp_stack, y, (; x)) - @test from == from_ - @test to == to_ - - y = [0.0, 1.0, -1.0, -1.0] - from = [0.0, 0.0, 0.0, -1.0] - to = [0.0, 1.0, -1.0, -2.0] - from_, to_ = stack_grouped_from_to(grp_stack, y, (; x)) - @test from == from_ - @test to == to_ - - y = [0.0, -1.0, -1.0, -1.0] - from = [0.0, 0.0, 0.0, -1.0] - to = [0.0, -1.0, -1.0, -2.0] - from_, to_ = stack_grouped_from_to(grp_stack, y, (; x)) - @test from == from_ - @test to == to_ - - y = [0.0, 1.0, -1.0, -1.0] - from = [0.0, 0.0, 0.0, -1.0] - to = [0.0, 1.0, -1.0, -2.0] - from_, to_ = stack_grouped_from_to(1:4, y, (; x=ones(4))) - @test from == from_ - @test to == to_ -end