Skip to content

Commit 7051fc8

Browse files
authored
change Requires.jl code to package extension (#111)
* change Requires.jl code to package extension * format * format * check for Julia v1.9.1 instead of isdefined(Base, :get_extension) * update Aqua.jl tests * bump version * fix typos
1 parent 3dc3ead commit 7051fc8

File tree

7 files changed

+193
-146
lines changed

7 files changed

+193
-146
lines changed

Project.toml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "RootedTrees"
22
uuid = "47965b36-3f3e-11e9-0dcf-4570dfd42a8c"
33
authors = ["Hendrik Ranocha <[email protected]> and contributors"]
4-
version = "2.18.2"
4+
version = "2.19.0"
55

66
[deps]
77
Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
@@ -10,9 +10,19 @@ Preferences = "21216c6a-2e73-6563-6e65-726566657250"
1010
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
1111
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
1212

13+
[weakdeps]
14+
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
15+
16+
[extensions]
17+
PlotsExt = "Plots"
18+
1319
[compat]
1420
Latexify = "0.15, 0.16"
21+
Plots = "1"
1522
Preferences = "1.3"
1623
RecipesBase = "1"
1724
Requires = "1"
1825
julia = "1.6"
26+
27+
[extras]
28+
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"

ext/PlotsExt.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module PlotsExt
2+
3+
# We do not check `isdefined(Base, :get_extension)` since Julia v1.9.0
4+
# does not load package extensions when their dependency is loaded from
5+
# the main environment
6+
if VERSION >= v"1.9.1"
7+
using Plots: Plots
8+
else
9+
import ..Plots: Plots
10+
end
11+
12+
using RootedTrees: RootedTrees
13+
14+
RootedTrees._distinguishable_colors(n) = Plots.distinguishable_colors(n)
15+
16+
end # module

src/RootedTrees.jl

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ using LinearAlgebra: dot
77
using Latexify: Latexify
88
using Preferences: @set_preferences!, @load_preference
99
using RecipesBase: RecipesBase
10-
using Requires: @require
10+
11+
# We do not check `isdefined(Base, :get_extension)` since Julia v1.9.0
12+
# does not load package extensions when their dependency is loaded from
13+
# the main environment
14+
if !(VERSION >= v"1.9.1")
15+
using Requires: @require
16+
end
1117

1218
export RootedTree, rootedtree, rootedtree!, RootedTreeIterator,
1319
ColoredRootedTree, BicoloredRootedTree, BicoloredRootedTreeIterator
@@ -1438,9 +1444,11 @@ function __init__()
14381444
Threads.resize_nthreads!(PARTITION_ITERATOR_BUFFER_EDGE_SET_TMP,
14391445
Vector{Bool}(undef, BUFFER_LENGTH))
14401446

1441-
@require Plots="91a5bcdd-55d7-5caf-9e0b-520d859cae80" begin
1442-
using .Plots: Plots
1443-
include("plots.jl")
1447+
# We do not check `isdefined(Base, :get_extension)` since Julia v1.9.0
1448+
# does not load package extensions when their dependency is loaded from
1449+
# the main environment
1450+
@static if !(VERSION >= v"1.9.1")
1451+
@require Plots="91a5bcdd-55d7-5caf-9e0b-520d859cae80" begin include("../ext/PlotsExt.jl") end
14441452
end
14451453

14461454
return nothing

src/plot_recipes.jl

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,146 @@ function _plot_coordinates(t::AbstractRootedTree,
8080

8181
return x, y
8282
end
83+
84+
# We load Plots.distinguishable_colors via Requires.jl for older versions
85+
# of Julia and as a package extension (weak dependency) on newer versions
86+
# of Julia.
87+
function _distinguishable_colors end
88+
89+
RecipesBase.@recipe function plot(t::ColoredRootedTree)
90+
# Compute x and y coordinates recursively
91+
width = 2.0
92+
height = 1.0
93+
color_idx = unique(t.color_sequence)
94+
if eltype(t.color_sequence) == Bool
95+
color_val = [:white, :black]
96+
else
97+
color_val = _distinguishable_colors(length(color_idx))
98+
end
99+
colormap = Dict{eltype(color_idx), eltype(color_val)}()
100+
for (idx, val) in zip(color_idx, color_val)
101+
colormap[idx] = val
102+
end
103+
x, y, colors = _plot_coordinates(t, 0.0, 0.0, width, height, colormap)
104+
105+
# Series properties
106+
linecolor --> :black
107+
markercolor --> reshape(colors, 1, :)
108+
background_color --> "LightGray"
109+
markershape --> :circle
110+
markersize --> 6
111+
linewidth --> 2
112+
113+
# Geometric properties
114+
grid --> false
115+
ticks --> false
116+
foreground_color_border --> :white
117+
legend --> :bottomright
118+
119+
# We need to `flatten` nested arrays
120+
if !isempty(t)
121+
x_min, x_max = extrema(Iterators.flatten(x))
122+
else
123+
x_min = x_max = zero(eltype(eltype(x)))
124+
end
125+
if x_min x_max
126+
xlims --> (x_min - width / 2, x_max + width / 2)
127+
end
128+
129+
if !isempty(t)
130+
y_min, y_max = extrema(Iterators.flatten(y))
131+
else
132+
y_min = y_max = zero(eltype(eltype(x)))
133+
end
134+
if y_min y_max
135+
ylims --> (y_min - height / 2, y_max + height / 2)
136+
end
137+
138+
# Annotations
139+
labels = ones(String, 1, length(colors))
140+
if !isempty(t)
141+
labels[1] = "tree " * string((t.level_sequence, t.color_sequence))
142+
end
143+
label --> labels
144+
145+
x, y
146+
end
147+
148+
function _plot_coordinates(t::ColoredRootedTree,
149+
x_root::T, y_root::T,
150+
width::T, height::T,
151+
colormap) where {T}
152+
# Initialize vectors of return values
153+
x = Vector{Vector{T}}()
154+
y = Vector{Vector{T}}()
155+
colors = Vector{Vector{valtype(colormap)}}()
156+
157+
if isempty(t)
158+
return x, y, colors
159+
end
160+
161+
push!(x, [x_root])
162+
push!(y, [y_root])
163+
color_root = colormap[first(t.color_sequence)]
164+
push!(colors, [color_root])
165+
166+
# We cannot indicate a new line series by `NaN` since that doesn't work with
167+
# colors
168+
# ┌ Warning: Indices Base.OneTo(9) of attribute `seriescolor` does not match data indices 3:9.
169+
# └ @ Plots ~/.julia/packages/Plots/AJMX6/src/utils.jl:132
170+
# ┌ Info: Data contains NaNs or missing values, and indices of `seriescolor` vector do not match data indices.
171+
# │ If you intend elements of `seriescolor` to apply to individual NaN-separated segments in the data,
172+
# │ pass each segment in a separate vector instead, and use a row vector for `seriescolor`. Legend entries
173+
# │ may be suppressed by passing an empty label.
174+
# │ For example,
175+
# └ plot([1:2,1:3], [[4,5],[3,4,5]], label=["y" ""], seriescolor=[1 2])
176+
# ┌ Warning: Indices Base.OneTo(9) of attribute `linecolor` does not match data indices 3:9.
177+
# └ @ Plots ~/.julia/packages/Plots/AJMX6/src/utils.jl:132
178+
# ┌ Info: Data contains NaNs or missing values, and indices of `linecolor` vector do not match data indices.
179+
# │ If you intend elements of `linecolor` to apply to individual NaN-separated segments in the data,
180+
# │ pass each segment in a separate vector instead, and use a row vector for `linecolor`. Legend entries
181+
# │ may be suppressed by passing an empty label.
182+
# │ For example,
183+
# └ plot([1:2,1:3], [[4,5],[3,4,5]], label=["y" ""], linecolor=[1 2])
184+
# ┌ Warning: Indices Base.OneTo(9) of attribute `fillcolor` does not match data indices 3:9.
185+
# └ @ Plots ~/.julia/packages/Plots/AJMX6/src/utils.jl:132
186+
# ┌ Info: Data contains NaNs or missing values, and indices of `fillcolor` vector do not match data indices.
187+
# │ If you intend elements of `fillcolor` to apply to individual NaN-separated segments in the data,
188+
# │ pass each segment in a separate vector instead, and use a row vector for `fillcolor`. Legend entries
189+
# │ may be suppressed by passing an empty label.
190+
# │ For example,
191+
# └ plot([1:2,1:3], [[4,5],[3,4,5]], label=["y" ""], fillcolor=[1 2])
192+
# ┌ Warning: Indices Base.OneTo(9) of attribute `markercolor` does not match data indices 3:9.
193+
# └ @ Plots ~/.julia/packages/Plots/AJMX6/src/utils.jl:132
194+
# ┌ Info: Data contains NaNs or missing values, and indices of `markercolor` vector do not match data indices.
195+
# │ If you intend elements of `markercolor` to apply to individual NaN-separated segments in the data,
196+
# │ pass each segment in a separate vector instead, and use a row vector for `markercolor`. Legend entries
197+
# │ may be suppressed by passing an empty label.
198+
# │ For example,
199+
# └ plot([1:2,1:3], [[4,5],[3,4,5]], label=["y" ""], markercolor=[1 2])
200+
201+
# Compute plot coordinates recursively
202+
subtr = subtrees(t)
203+
204+
# Distribute children uniformly in x and at equal y coordinates
205+
y_child = y_root + height
206+
num_children = length(subtr)
207+
distance = width * (num_children - 1) / 2
208+
209+
x_children = range(x_root - distance, x_root + distance, length = num_children)
210+
for idx in eachindex(subtr)
211+
x_child = x_children[idx]
212+
push!(x, [x_root, x_child])
213+
push!(y, [y_root, y_child])
214+
push!(colors, [color_root, colormap[first(subtr[idx].color_sequence)]])
215+
x_recursive, y_recursive, colors_recursive = _plot_coordinates(subtr[idx],
216+
x_child, y_child,
217+
width / 3, height,
218+
colormap)
219+
append!(x, x_recursive)
220+
append!(y, y_recursive)
221+
append!(colors, colors_recursive)
222+
end
223+
224+
return x, y, colors
225+
end

src/plots.jl

Lines changed: 0 additions & 138 deletions
This file was deleted.

test/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
66
UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228"
77

88
[compat]
9-
Aqua = "0.5, 0.6"
9+
Aqua = "0.6.1"
1010
Plots = "1"
1111
StaticArrays = "1.3"
1212
UnicodePlots = "2, 3"

test/runtests.jl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,6 +1717,14 @@ using Aqua: Aqua
17171717
end
17181718
end # @testset "plots"
17191719

1720-
@testset "Aqua" begin Aqua.test_all(RootedTrees;
1721-
ambiguities = (; exclude = [getindex])) end
1720+
@testset "Aqua" begin
1721+
Aqua.test_all(RootedTrees;
1722+
ambiguities = (; exclude = [getindex]),
1723+
# New Project.toml tests fail on old versions of Julia
1724+
project_toml_formatting = false)
1725+
1726+
if VERSION >= v"1.9.0"
1727+
Aqua.test_project_toml_formatting(RootedTrees)
1728+
end
1729+
end
17221730
end # @testset "RootedTrees"

0 commit comments

Comments
 (0)