Skip to content

Commit

Permalink
Improve docs and tie things together
Browse files Browse the repository at this point in the history
  • Loading branch information
asinghvi17 committed Mar 9, 2024
1 parent 2b220b5 commit 46f0ce2
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 13 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
/docs/Manifest.toml
/docs/build/
/docs/package-lock.json
/docs/src/source
/docs/src/source
*/node_modules/*
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ authors = ["Anshul Singhvi <[email protected]>", "Jacob Zelko <jacobszelko
version = "0.0.1-DEV"

[deps]
KernelDensity = "5ab0869b-81aa-558d-bb23-cbf5423bbe9b"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

Expand Down
2 changes: 2 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[deps]
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
DocumenterVitepress = "4710194d-e776-4893-9690-8d956a29c365"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b"
SwarmMakie = "0b1c068e-6a84-4e66-8136-5c95cafa83ed"
61 changes: 60 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,78 @@
using SwarmMakie
using Documenter, DocumenterVitepress
using Documenter, DocumenterVitepress, Literate
using CairoMakie

CairoMakie.activate!(type="svg", pt_per_unit = 0.75)

DocMeta.setdocmeta!(SwarmMakie, :DocTestSetup, :(using SwarmMakie); recursive=true)


# Now, we convert the source code to markdown files using Literate.jl
source_path = joinpath(dirname(@__DIR__), "src")
output_path = joinpath(@__DIR__, "src", "source")
mkpath(output_path)

literate_pages = Any[]

# We don't want Literate to convert the code into Documenter blocks, so we use a custom postprocessor
# to add the `@meta` block to the markdown file, which will be used by Documenter to add an edit link.
function _add_meta_edit_link_generator(path)
return function (input)
return """
```@meta
EditURL = "$(path).jl"
```
""" * input # we add `.jl` because `relpath` eats the file extension, apparently :shrug:
end
end

# First letter of `str` is made uppercase and returned
ucfirst(str::String) = string(uppercase(str[1]), str[2:end])

function process_literate_recursive!(pages::Vector{Any}, path::String; source_path, output_path)
if isdir(path)
contents = []
process_literate_recursive!.((contents,), normpath.(readdir(path; join = true)); source_path, output_path)
push!(pages, ucfirst(splitdir(path)[2]) => 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 <[email protected]>, Jacob Zelko <[email protected]>, Michael Krabbe Borregaard <[email protected]>, and contributors",
sitename="SwarmMakie.jl",
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(;
Expand Down
3 changes: 3 additions & 0 deletions docs/src/algorithms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Algorithms

SwarmMakie offers several beeswarm algorithms, which give different results.
8 changes: 8 additions & 0 deletions docs/src/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# API Reference

```@index
```

```@autodocs; canonical=true
Modules = [SwarmMakie]
```
20 changes: 15 additions & 5 deletions docs/src/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```

1 change: 1 addition & 0 deletions src/SwarmMakie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ using Makie, Random

include("recipe.jl")
include("algorithms/simple.jl")
include("algorithms/mkborregaard.jl")

end
23 changes: 19 additions & 4 deletions src/algorithms/mkborregaard.jl
Original file line number Diff line number Diff line change
@@ -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)

Expand Down Expand Up @@ -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()))
x,y = SwarmMakie.beeswarm_coords(collect(iris[!, :SepalLength]), :both)
Makie.scatter(x,y, color = iris[!, :Species].refs, markersize = 7, axis = (; aspect = DataAspect()))
```
=#
12 changes: 10 additions & 2 deletions src/algorithms/simple.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# # Simple beeswarm

export SimpleBeeswarm

"""
SimpleBeeswarm()
Expand All @@ -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
5 changes: 5 additions & 0 deletions src/recipe.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# # Beeswarm recipe

export beeswarm, beeswarm!

export NoBeeswarm

# In this file, we define the `Beeswarm` recipe.

@recipe(Beeswarm, positions) do scene
Expand All @@ -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`)."
Expand Down

0 comments on commit 46f0ce2

Please sign in to comment.