diff --git a/docs/src/algorithms.md b/docs/src/algorithms.md index 5c8ab53..f49ad0e 100644 --- a/docs/src/algorithms.md +++ b/docs/src/algorithms.md @@ -19,7 +19,6 @@ ax_plots = [beeswarm(fig[Tuple(idx)...], xs, ys; color = xs, algorithm = algorit jitter_plots = getproperty.(ax_plots[2, :], :plot) setproperty!.(jitter_plots, :markersize, 7) setproperty!.(jitter_plots, :alpha, 0.3) -Makie.update_state_before_display!(fig) fig ``` diff --git a/docs/src/examples/examples.jl b/docs/src/examples/examples.jl index bf63281..3b2a18c 100644 --- a/docs/src/examples/examples.jl +++ b/docs/src/examples/examples.jl @@ -22,9 +22,6 @@ using PalmerPenguins, DataFrames penguins = dropmissing(DataFrame(PalmerPenguins.load())) f = data(penguins) * mapping(:species, :bill_depth_mm, color=:sex) * visual(Beeswarm) |> draw -Makie.update_state_before_display!(f.figure) -Makie.update_state_before_display!(f.figure) -Makie.update_state_before_display!(f.figure) f # ## SwarmMakie logo @@ -43,10 +40,6 @@ f.scene.backgroundcolor[] = RGBAf(1,1,1,0) a.scene.backgroundcolor[] = RGBAf(1,1,1,0) hidedecorations!(a) hidespines!(a) -Makie.update_state_before_display!(f) -Makie.update_state_before_display!(f) -Makie.update_state_before_display!(f) -Makie.update_state_before_display!(f) f # ## Wilkinson's dot histogram diff --git a/docs/src/introduction.md b/docs/src/introduction.md index 10dab2d..cf7b8b4 100644 --- a/docs/src/introduction.md +++ b/docs/src/introduction.md @@ -35,8 +35,6 @@ iris = dataset("datasets", "iris") f = data(iris) * mapping(:Species, :SepalLength; color = :Species) * visual(Beeswarm) |> draw -Makie.update_state_before_display!(f.figure) -Makie.update_state_before_display!(f.figure) f ``` @@ -44,4 +42,3 @@ f If your beeswarms are overlapping, or extending outside the axis area, try decreasing `markersize`. You can do this by setting `plot.markersize = 6` for example, and then re-displaying the figure. -Generally, the algorithm takes a few iterations of calling `Makie.update_state_before_display!(figure)` to settle in a good configuration. We are working to fix this. diff --git a/src/recipe.jl b/src/recipe.jl index c5ecb19..09b2c6e 100644 --- a/src/recipe.jl +++ b/src/recipe.jl @@ -60,7 +60,46 @@ function calculate!(buffer::AbstractVector{<: Point2}, alg::NoBeeswarm, position return end -Makie.data_limits(bs::Beeswarm) = Makie.data_limits(bs.plots[1]) +# Beeswarm plots inherently have an extent that is dependent on the placement +# algorithm and the available space. However, you cannot use the actual placement +# of scatter dots to infer limits, because adjusting the axis given these limits +# invalidates the limits again, and so on, potentially ad infinitum. +# +# Instead, it makes more sense to pick fixed limits given the input data. If +# that doesn't leave enough place for all beeswarms, probably the axis size +# has to be increased, or the marker sized decreased, anyway. +# +# The dimension that's not controlled by the beeswarm placement algorithm we +# can take directly from the input data. For the "categories" or group placement +# values, we simply determine the differences between the unique sorted values and +# increase the width at the sides by half the minimum distance. That means, we create +# equal space for all categories. If the beeswarm doesn't fit that, again, other +# parameters have to be adjusted anway. +function Makie.data_limits(bs::Beeswarm) + points = bs.converted[1][] + categories = sort(unique(p[1] for p in points)) + range_1 = if length(categories) == 1 + (only(categories) - 0.5, only(categories) + 0.5) + else + mindiff = if isnothing(bs.gutter[]) + minimum(diff(categories)) + else + bs.gutter[] + end + (first(categories) - mindiff/2, last(categories) + mindiff/2) + end + range_2 = extrema(p[2] for p in points) + bb = if bs.direction[] === :y + BBox(range_1..., range_2...) + elseif bs.direction[] === :x + BBox(range_2..., range_1...) + else + error("Invalid direction $(repr(bs.direction[])), expected :x or :y") + end + return Rect3f(bb) +end + +Makie.boundingbox(s::Beeswarm, space::Symbol = :data) = Makie.apply_transform_and_model(s, Makie.data_limits(s)) function Makie.plot!(plot::Beeswarm) positions = plot.converted[1] # being PointBased, it should always receive a vector of Point2 diff --git a/test/runtests.jl b/test/runtests.jl index 5cb9247..4fb8410 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -28,8 +28,6 @@ buffer = deepcopy(pixel_points) hidedecorations!(a) hidespines!(a) Makie.update_state_before_display!(f) - Makie.update_state_before_display!(f) - Makie.update_state_before_display!(f) img = Makie.colorbuffer(f.scene; px_per_unit = 1, pt_per_unit = 1, antialias = :none, visible = true, start_renderloop = false) # We have a matrix of all colors in the image. Now, what we do is the following: # The color white in RGBf is (1, 1, 1). For a color to be red, the blue and green components @@ -53,16 +51,13 @@ buffer = deepcopy(pixel_points) # First, we test the regular gutter with multiple categories. f, a, p = beeswarm(rand(1:3, 300), randn(300); color = rand(RGBAf, 300), markersize = 20, algorithm = SimpleBeeswarm()) Makie.update_state_before_display!(f) - Makie.update_state_before_display!(f) - @test_warn "Gutter threshold exceeded" p.gutter = 0.5 + @test_warn "Gutter threshold exceeded" p.gutter = 0.2 # Next, we test it in direction y - f, a, p = beeswarm(rand(1:3, 300), randn(300); direction = :x, color = rand(RGBAf, 300), markersize = 20, algorithm = SimpleBeeswarm()) - Makie.update_state_before_display!(f) + f, a, p = beeswarm(rand(1:3, 300), randn(300); direction = :x, color = rand(RGBAf, 300), markersize = 20, algorithm = SimpleBeeswarm()) Makie.update_state_before_display!(f) - @test_warn "Gutter threshold exceeded" p.gutter = 0.5 + @test_warn "Gutter threshold exceeded" p.gutter = 0.2 # and it shouldn't warn if, when using a lower markersize, the gutter is not reached. - f, a, p = beeswarm(rand(1:3, 300), randn(300); direction = :y, color = rand(RGBAf, 300), markersize = 9, algorithm = SimpleBeeswarm()) - Makie.update_state_before_display!(f) + f, a, p = beeswarm(rand(1:3, 300), randn(300); direction = :y, color = rand(RGBAf, 300), markersize = 9, algorithm = SimpleBeeswarm()) Makie.update_state_before_display!(f) @test_nowarn p.gutter = 0.5 end