diff --git a/.gitignore b/.gitignore index c68d8d2..290720d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ /docs/Manifest.toml /docs/build/ /docs/package-lock.json -/docs/src/source \ No newline at end of file +/docs/src/source +*/node_modules/* \ No newline at end of file diff --git a/Project.toml b/Project.toml index 04d4e1e..3e946f8 100644 --- a/Project.toml +++ b/Project.toml @@ -4,6 +4,7 @@ authors = ["Anshul Singhvi ", "Jacob Zelko contents) + elseif isfile(path) + if endswith(path, ".jl") + relative_path = relpath(path, source_path) + output_dir = joinpath(output_path, splitdir(relative_path)[1]) + Literate.markdown( + path, output_dir; + flavor = Literate.CommonMarkFlavor(), + postprocess = _add_meta_edit_link_generator(joinpath(relpath(source_path, output_dir), relative_path)) + ) + push!(pages, joinpath("source", splitext(relative_path)[1] * ".md")) + end + end +end + +withenv("JULIA_DEBUG" => "Literate") do # allow Literate debug output to escape to the terminal! + global literate_pages + vec = [] + process_literate_recursive!(vec, source_path; source_path, output_path) + literate_pages = vec[1][2] # this is a hack to get the pages in the correct order, without an initial "src" folder. + # TODO: We should probably fix the above in `process_literate_recursive!`. +end + makedocs(; modules=[SwarmMakie], authors="Anshul Singhvi , Jacob Zelko , Michael Krabbe Borregaard , and contributors", @@ -10,10 +64,15 @@ makedocs(; format=DocumenterVitepress.MarkdownVitepress(; repo = "https://github.com/asinghvi17/SwarmMakie.jl", devurl = "dev", + devbranch = "main", ), pages=[ "Introduction" => "introduction.md", + "Algorithms" => "algorithms.md", + "API Reference" => "api.md", + "Source code" => literate_pages, ], + warnonly = true, ) deploydocs(; diff --git a/docs/src/algorithms.md b/docs/src/algorithms.md new file mode 100644 index 0000000..c92e37d --- /dev/null +++ b/docs/src/algorithms.md @@ -0,0 +1,3 @@ +# Algorithms + +SwarmMakie offers several beeswarm algorithms, which give different results. \ No newline at end of file diff --git a/docs/src/api.md b/docs/src/api.md new file mode 100644 index 0000000..024993c --- /dev/null +++ b/docs/src/api.md @@ -0,0 +1,8 @@ +# API Reference + +```@index +``` + +```@autodocs; canonical=true +Modules = [SwarmMakie] +``` \ No newline at end of file diff --git a/docs/src/introduction.md b/docs/src/introduction.md index 048fac4..cf2ccb1 100644 --- a/docs/src/introduction.md +++ b/docs/src/introduction.md @@ -4,12 +4,22 @@ CurrentModule = SwarmMakie # SwarmMakie -`SwarmMakie` +`SwarmMakie` implements beeswarm or swarm plots in Makie. These are scatter plots which are categorical (or singular) in the x-axis, where the markers are nudged so that each marker is visible and avoids overlap. +The main entry point to the package is the [`beeswarm`](@ref) recipe, which takes the same arguments as Makie's `scatter` plots, and transforms them into a beautiful beeswarm plot! -```@index -``` +Being a Makie recipe, you can also use this with AlgebraOfGraphics. + +## Quick start -```@autodocs -Modules = [SwarmMakie] +Here's a quick example to get you started: + +```@example quickstart +using CairoMakie, SwarmMakie +xs = rand(1:3, 40) +ys = randn(40) +f, a, p = scatter(xs, ys; color = xs) +beeswarm(f[1, 2], xs, ys; color = xs, algorithm = NoBeeswarm()) +f ``` + diff --git a/src/SwarmMakie.jl b/src/SwarmMakie.jl index 4a5d18c..44a14ac 100644 --- a/src/SwarmMakie.jl +++ b/src/SwarmMakie.jl @@ -6,5 +6,6 @@ using Makie, Random include("recipe.jl") include("algorithms/simple.jl") +include("algorithms/mkborregaard.jl") end diff --git a/src/algorithms/mkborregaard.jl b/src/algorithms/mkborregaard.jl index c28cc0d..fca6faf 100644 --- a/src/algorithms/mkborregaard.jl +++ b/src/algorithms/mkborregaard.jl @@ -1,3 +1,14 @@ +# Michael Borregaard's beeswarm + +export MKBorregaardBeeswarm + +struct MKBorregaardBeeswarm <: BeeswarmAlgorithm end + +function calculate!(buffer::AbstractVector{<: Point2}, alg::MKBorregaardBeeswarm, positions::AbstractVector{<: Point2}, markersize) + x, y = beeswarm_coords(last.(positions)) + buffer .= Point2f.(x, y) +end + function beeswarm_coords(olda, side = :both) @@ -108,11 +119,15 @@ function beeswarm_coords(olda, side = :both) rety, olda end -x,y = beeswarm_coords(collect(iris[!, :SepalLength]), :both) +#= +```@example +using DataFrames, RDatasets +using SwarmMakie, CairoMakie -using DataFrames, RDatasets #, Plots iris = dataset("datasets", "iris") -x,y = beeswarm_coords(collect(iris[!, :SepalLength]), :both) -Makie.scatter(x,y, color = iris[!, :Species].refs, markersize = 7, axis = (; aspect = DataAspect())) \ No newline at end of file +x,y = SwarmMakie.beeswarm_coords(collect(iris[!, :SepalLength]), :both) +Makie.scatter(x,y, color = iris[!, :Species].refs, markersize = 7, axis = (; aspect = DataAspect())) +``` +=# \ No newline at end of file diff --git a/src/algorithms/simple.jl b/src/algorithms/simple.jl index 5444c28..8fc1863 100644 --- a/src/algorithms/simple.jl +++ b/src/algorithms/simple.jl @@ -1,3 +1,7 @@ +# # Simple beeswarm + +export SimpleBeeswarm + """ SimpleBeeswarm() @@ -7,7 +11,11 @@ struct SimpleBeeswarm <: BeeswarmAlgorithm end function calculate!(buffer::AbstractVector{<: Point2}, alg::SimpleBeeswarm, positions::AbstractVector{<: Point2}, markersize) - - buffer .= positions + ys = last.(positions) + ymin, ymax = extrema(ys) + nbins = (ymax - ymin) รท markersize + dy = markersize + ybins = LinRange(ymin+dy, ymax-dy, nbins-1) # this is a center list of bins + i = eachindex(ys) return end diff --git a/src/recipe.jl b/src/recipe.jl index b0a189b..30d585f 100644 --- a/src/recipe.jl +++ b/src/recipe.jl @@ -1,5 +1,9 @@ # # Beeswarm recipe +export beeswarm, beeswarm! + +export NoBeeswarm + # In this file, we define the `Beeswarm` recipe. @recipe(Beeswarm, positions) do scene @@ -26,6 +30,7 @@ function calculate!(buffer::AbstractVector{<: Point2}, alg::NoBeeswarm, position end Makie.data_limits(bs::Beeswarm) = Makie.data_limits(bs.plots[1]) + function Makie.plot!(plot::Beeswarm) positions = plot.converted[1] # being PointBased, it should always receive a vector of Point2 @assert positions[] isa AbstractVector{<: Point2} "`positions` should be an `AbstractVector` of `Point2` after conversion, got type $(typeof(positions)). If you have passed in `x, y, z` input, be aware that `beeswarm` only accepts 2-D input (`x, y`)."