Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
ae22f5d
remove implicit cycling
BeastyBlacksmith Oct 23, 2025
e103325
adjust compat bounds
BeastyBlacksmith Oct 26, 2025
673acfc
fix example 1
BeastyBlacksmith Oct 26, 2025
736dfa4
fix more examples
BeastyBlacksmith Oct 29, 2025
962bc41
cleanup GRExt
BeastyBlacksmith Oct 29, 2025
864613a
cleanup GastonExt
BeastyBlacksmith Oct 29, 2025
3977448
cleanup PGFPlotsXExt
BeastyBlacksmith Oct 29, 2025
6b04ae3
format
BeastyBlacksmith Oct 29, 2025
fee0ee3
cleanup PythonPlotExt
BeastyBlacksmith Oct 29, 2025
c002da1
cleanup Annotations
BeastyBlacksmith Oct 29, 2025
3187017
more cleanups
BeastyBlacksmith Oct 29, 2025
cf9e6c2
finish plotly
BeastyBlacksmith Oct 29, 2025
0778d32
finish cleanup PlotsBase
BeastyBlacksmith Oct 30, 2025
d366568
cleanup StatsPlots
BeastyBlacksmith Oct 30, 2025
51798a0
fix lens recipe
BeastyBlacksmith Oct 30, 2025
f99729f
fix color handling of series
BeastyBlacksmith Oct 30, 2025
98ee31b
enable scalar cycling
BeastyBlacksmith Nov 3, 2025
3dc32e6
improve GraphRecipes tests
BeastyBlacksmith Nov 3, 2025
2956dc7
use using where possible in Subplots
BeastyBlacksmith Nov 3, 2025
c4be23f
fix explicit series attribute retrieval
BeastyBlacksmith Nov 3, 2025
53378b2
fix use of non-existent markerstrokesize
BeastyBlacksmith Nov 3, 2025
64d3a97
fix line_z, etc
BeastyBlacksmith Nov 3, 2025
4535f03
fix GraphRecipes tests
BeastyBlacksmith Nov 3, 2025
3ab43ae
get closer to resolve slicing and cycling interaction
BeastyBlacksmith Nov 3, 2025
0c1b467
make more sense of ribbon tests
BeastyBlacksmith Jan 9, 2026
e68ca43
add fix to the tests
BeastyBlacksmith Feb 2, 2026
309ab0e
Merge branch 'v2' into bbs/v2/no-cycling
BeastyBlacksmith Feb 3, 2026
12cbab3
Fix imports
BeastyBlacksmith Feb 3, 2026
ebbc9c9
more fixes
BeastyBlacksmith Feb 3, 2026
fe92eb9
handle palettes
BeastyBlacksmith Feb 5, 2026
2b52c02
Merge branch 'v2' into bbs/v2/no-cycling
BeastyBlacksmith Feb 5, 2026
6b5193b
add guard in gaston
BeastyBlacksmith Feb 9, 2026
f3a9814
fix GraphRecipes testpath
BeastyBlacksmith Feb 10, 2026
741fa2a
fix offsetarrays
BeastyBlacksmith Feb 10, 2026
725db24
fix handling of grouped barplots
BeastyBlacksmith Feb 10, 2026
a75e82b
handle 0s
BeastyBlacksmith Feb 10, 2026
efb170a
fix indexing in single color, GraphRecipes test file
BeastyBlacksmith Feb 10, 2026
b88906a
fix format
BeastyBlacksmith Feb 10, 2026
13bc659
fix GraphRecipes test
BeastyBlacksmith Feb 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions GraphRecipes/src/GraphRecipes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module GraphRecipes
using Graphs
using PlotUtils # ColorGradient
using RecipesBase
using PlotsBase: PlotsBase, partialcircle

using InteractiveUtils # subtypes
using LinearAlgebra
Expand Down
4 changes: 2 additions & 2 deletions GraphRecipes/src/graphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1132,7 +1132,7 @@ more details.
colorbar_entry --> false
markersize := 0
markeralpha := 0
markerstrokesize := 0
makerstrokewidth := 0
isnothing(edgelabel) || (annotations --> edge_label_array)
else
seriestype := :scatter
Expand All @@ -1153,7 +1153,7 @@ more details.
colorbar_entry --> false
markersize := 0
markeralpha := 0
markerstrokesize := 0
makerstrokewidth := 0
annotations --> edge_label_array
end
end
Expand Down
9 changes: 1 addition & 8 deletions GraphRecipes/src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -261,15 +261,8 @@ function process_edge_attribute(attr, source, destiny, weights)
end
return attr
end
# Function from Plots/src/components.jl
"get an array of tuples of points on a circle with radius `r`"
function partialcircle(start_θ, end_θ, n = 20, r = 1)
return Tuple{Float64, Float64}[
(r * cos(u), r * sin(u)) for u in range(start_θ, stop = end_θ, length = n)
]
end

function partialcircle(start_θ, end_θ, circle_center::Array{T, 1}, n = 20, r = 1) where {T}
function PlotsBase.Shapes.partialcircle(start_θ, end_θ, circle_center::Array{T, 1}, n = 20, r = 1) where {T}
return Tuple{Float64, Float64}[
(r * cos(u) + circle_center[1], r * sin(u) + circle_center[2]) for
u in range(start_θ, stop = end_θ, length = n)
Expand Down
4 changes: 4 additions & 0 deletions GraphRecipes/test/functions.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
using AbstractTrees
using StableRNGs
using GraphRecipes.Graphs

function random_labelled_graph()
n = 15
rng = StableRNG(1)
Expand Down
2 changes: 1 addition & 1 deletion GraphRecipes/test/parse_readme.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ end
# the installation instructions.
readme_exprs = [Meta.parse("begin $(code_blocks[i]) end") for i in 2:length(code_blocks)]

julia_logo_pun() = eval(readme_exprs[1])
readme_julia_logo_pun() = eval(readme_exprs[1])
84 changes: 33 additions & 51 deletions GraphRecipes/test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
using VisualRegressionTests
using AbstractTrees
using LinearAlgebra
using GraphRecipes
using Logging
using GraphRecipes
using SparseArrays
using ImageMagick
using StableRNGs
using Logging
using Graphs
using Plots
using Plots.PlotsBase
using Test
using Gtk # for popup

const PlotsBase = Plots.PlotsBase

isci() = get(ENV, "CI", "false") == "true"
itol(tol = nothing) = something(tol, isci() ? 1.0e-3 : 1.0e-5)

Expand All @@ -22,45 +20,29 @@ include("parse_readme.jl")

default(show = false, reuse = true)

@testset "functions" begin
rng = StableRNG(1)
for method in keys(GraphRecipes._graph_funcs)
method ≡ :spectral && continue # FIXME
dat = if (inp = GraphRecipes._graph_inputs[method]) ≡ :adjmat
[
0 1 1
1 0 1
1 1 0
]
elseif inp ≡ :sourcedestiny
Symmetric(sparse(rand(rng, 0:1, 8, 8)))
elseif inp ≡ :adjlist
dat = [
0 1 1 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 1 0 0 1 0 1 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 1
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
]
else
@error "wrong input $inp"
cd(joinpath(@__DIR__, "..", "..", "assets", "GraphRecipes")) do
@testset "TestImages" begin
figure_files = readdir()
@testset "$figure_file" for figure_file in figure_files
figure = splitext(figure_file)[1]
if figure == "julia_type_tree"
if VERSION >= v"1.11" # julia 1.11 introduced Core.BFloat16
@plottest julia_type_tree() "julia_type_tree.png" popup = !isci() tol = itol()
end
else
@plottest getproperty(@__MODULE__, Symbol(figure))() figure_file popup = !isci() tol =
itol()
end
end
pl = graphplot(dat; method)
@test pl isa PlotsBase.Plot
end
end

@testset "issues" begin
@testset "143" begin
g = SimpleGraph(7)

add_edge!(g, 2, 3)
add_edge!(g, 3, 4)

@test g.ne == 2
al = GraphRecipes.get_adjacency_list(g)
@test isempty(al[1])
Expand Down Expand Up @@ -96,22 +78,22 @@ end
@testset "180" begin
rng = StableRNG(1)
mat = Symmetric(sparse(rand(rng, 0:1, 8, 8)))
graphplot(mat; method = :arcdiagram, rng)
graphplot(mat, method = :arcdiagram, rng = rng)
end
end

@testset "utils.jl" begin
rng = StableRNG(1)
@test GraphRecipes.directed_curve(0.0, 1.0, 0.0, 1.0; rng) ==
GraphRecipes.directed_curve(0, 1, 0, 1; rng)
@test GraphRecipes.directed_curve(0.0, 1.0, 0.0, 1.0, rng = rng) ==
GraphRecipes.directed_curve(0, 1, 0, 1, rng = rng)

@test GraphRecipes.isnothing(nothing) == PlotsBase.isnothing(nothing)
@test GraphRecipes.isnothing(missing) == PlotsBase.isnothing(missing)
@test GraphRecipes.isnothing(NaN) == PlotsBase.isnothing(NaN)
@test GraphRecipes.isnothing(0) == PlotsBase.isnothing(0)
@test GraphRecipes.isnothing(1) == PlotsBase.isnothing(1)
@test GraphRecipes.isnothing(0.0) == PlotsBase.isnothing(0.0)
@test GraphRecipes.isnothing(1.0) == PlotsBase.isnothing(1.0)
@test GraphRecipes.isnothing(nothing) == Plots.isnothing(nothing)
@test GraphRecipes.isnothing(missing) == Plots.isnothing(missing)
@test GraphRecipes.isnothing(NaN) == Plots.isnothing(NaN)
@test GraphRecipes.isnothing(0) == Plots.isnothing(0)
@test GraphRecipes.isnothing(1) == Plots.isnothing(1)
@test GraphRecipes.isnothing(0.0) == Plots.isnothing(0.0)
@test GraphRecipes.isnothing(1.0) == Plots.isnothing(1.0)

for (s, e) in [(rand(rng), rand(rng)) for i in 1:100]
@test GraphRecipes.partialcircle(s, e) == PlotsBase.partialcircle(s, e)
Expand Down Expand Up @@ -144,12 +126,12 @@ end
# checking that they don't error. Also, test all of the different aliases.
@testset "Aliases" begin
A = [1 0 1 0; 0 0 1 1; 1 1 1 1; 0 0 1 1]
graphplot(A; markercolor = :red, markershape = :rect, markersize = 0.5, rng)
graphplot(A; nodeweights = 1:4, rng)
graphplot(A; curvaturescalar = 0, rng)
graphplot(A; el = Dict((1, 2) => ""), elb = true, rng)
graphplot(A; ew = (s, d, w) -> 3, rng)
graphplot(A; ses = 0.5, rng)
graphplot(A, markercolor = :red, markershape = :rect, markersize = 0.5, rng = rng)
graphplot(A, nodeweights = 1:4, rng = rng)
graphplot(A, curvaturescalar = 0, rng = rng)
graphplot(A, el = Dict((1, 2) => ""), elb = true, rng = rng)
graphplot(A, ew = (s, d, w) -> 3, rng = rng)
graphplot(A, ses = 0.5, rng = rng)
end
end

Expand Down Expand Up @@ -190,6 +172,6 @@ cd(joinpath(@__DIR__, "..", "..", "assets", "GraphRecipes")) do
end

@testset "README" begin
@plottest julia_logo_pun() "readme_julia_logo_pun.png" popup = !isci() tol = itol()
@plottest readme_julia_logo_pun() "readme_julia_logo_pun.png" popup = !isci() tol = itol()
end
end
2 changes: 1 addition & 1 deletion PlotsBase/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ Preferences = "1"
Printf = "1"
PythonPlot = "1"
REPL = "1"
RecipesBase = "1.4.0"
Random = "1"
RecipesBase = "1.3.1"
RecipesPipeline = "1"
Reexport = "1"
Scratch = "1"
Expand Down
35 changes: 18 additions & 17 deletions PlotsBase/ext/GRExt.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module GRExt

import PlotsBase: PlotsBase, PrecompileTools, RecipesPipeline, _cycle
import PlotsBase: PlotsBase, PrecompileTools, RecipesPipeline

import NaNMath
import GR
Expand Down Expand Up @@ -331,11 +331,11 @@ function gr_getcolorind(c)
return convert(Int, GR.inqcolorfromrgb(red(c), green(c), blue(c)))
end

gr_set_linecolor(c) = GR.setlinecolorind(gr_getcolorind(_cycle(c, 1)))
gr_set_fillcolor(c) = GR.setfillcolorind(gr_getcolorind(_cycle(c, 1)))
gr_set_markercolor(c) = GR.setmarkercolorind(gr_getcolorind(_cycle(c, 1)))
gr_set_bordercolor(c) = GR.setbordercolorind(gr_getcolorind(_cycle(c, 1)))
gr_set_textcolor(c) = GR.settextcolorind(gr_getcolorind(_cycle(c, 1)))
gr_set_linecolor(c::Colorant) = GR.setlinecolorind(gr_getcolorind(c))
gr_set_fillcolor(c::Colorant) = GR.setfillcolorind(gr_getcolorind(c))
gr_set_markercolor(c::Colorant) = GR.setmarkercolorind(gr_getcolorind(c))
gr_set_bordercolor(c::Colorant) = GR.setbordercolorind(gr_getcolorind(c))
gr_set_textcolor(c::Colorant) = GR.settextcolorind(gr_getcolorind(c))
gr_set_transparency(α::Real) = GR.settransparency(clamp(α, 0, 1))
gr_set_transparency(::Nothing) = GR.settransparency(1)
gr_set_transparency(c, α) = gr_set_transparency(α)
Expand Down Expand Up @@ -518,7 +518,7 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
# draw radial ticks
yaxis[:showaxis] && for i in eachindex(rtick_values)
r = (rtick_values[i] - rmin) / (rmax - rmin)
(r ≤ 1 && r ≥ 0) && gr_text(GR.wctondc(0.05, r)..., _cycle(rtick_labels, i))
(r ≤ 1 && r ≥ 0) && gr_text(GR.wctondc(0.05, r)..., _getvalue(rtick_labels, i))
end
GR.restorestate()
return nothing
Expand Down Expand Up @@ -1288,7 +1288,7 @@ function gr_add_legend(sp, leg, viewport_area)
1,
min(max_markersize, mfac * msz),
min(max_markersize, mfac * msw),
_cycle(msh, 1),
_getvalue(msh, 1),
)
end

Expand Down Expand Up @@ -2027,8 +2027,8 @@ function gr_draw_segments(series, x, y, z, fillrange, clims)
if is2d && fillrange ≢ nothing
(fc = get_fillcolor(series, clims, i)) |> gr_set_fillcolor
gr_set_fillstyle(get_fillstyle(series, i))
fx = _cycle(x, vcat(rng, reverse(rng)))
fy = vcat(_cycle(fr_from, rng), _cycle(fr_to, reverse(rng)))
fx = _getvalue(x, vcat(rng, reverse(rng)))
fy = vcat(_getvalue(fr_from, rng), _getvalue(RecipesBase.cycle(fr_to), reverse(rng)))
gr_set_transparency(fc, get_fillalpha(series, i))
GR.fillarea(fx, fy)
end
Expand Down Expand Up @@ -2066,18 +2066,18 @@ function gr_draw_markers(
rng = intersect(eachindex(IndexLinear(), x), segment.range)
isempty(rng) && continue
i = segment.attr_index
ms = get_thickness_scaling(series) * _cycle(msize, i)
msw = get_thickness_scaling(series) * _cycle(strokewidth, i)
shape = _cycle(shapes, i)
ms = get_thickness_scaling(series) * _getvalue(msize, i)
msw = get_thickness_scaling(series) * _getvalue(strokewidth, i)
shape = _getvalue(shapes, i)
if !(shape isa Shape)
shape = gr_get_markershape.(shape)
end
for j in rng
gr_draw_marker(
series,
_cycle(x, j),
_cycle(y, j),
_cycle(z, j),
_getvalue(x, j),
_getvalue(y, j),
_getvalue(z, j),
clims,
i,
ms,
Expand Down Expand Up @@ -2148,7 +2148,8 @@ function gr_draw_surface(series, x, y, z, clims)
x, y, z = GR.gridit(x, y, z, nx, ny)
end
d_opt = get(e_kwargs, :display_option, GR.OPTION_COLORED_MESH)
if (!isnothing(fillalpha) && fillalpha < 1) || alpha(first(fillcolor)) < 1
fc = fillcolor isa Colorant ? fillcolor : first(fillcolor)
if (!isnothing(fillalpha) && fillalpha < 1) || alpha(fc) < 1
gr_set_transparency(fillcolor, fillalpha)
GR.surface(x, y, z, d_opt)
else
Expand Down
12 changes: 8 additions & 4 deletions PlotsBase/ext/GastonExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -327,9 +327,13 @@ function gaston_add_series(plt::Plot{GastonBackend}, series::Series)
if !gsp.is3d && z ≡ nothing
for (n, seg) in enumerate(series_segments(series, st; check = true))
i, rng = seg.attr_index, seg.range
fr = _cycle(series[:fillrange], 1:length(x[rng]))
fr = _getattr(series, :fillrange, 1:length(x[rng]))
for sc in gaston_seriesconf!(sp, series, n == 1, i)
push!(gsp.plots, Gaston.Plot(x[rng], y[rng], fr, sc))
if fr ≡ nothing
push!(gsp.plots, Gaston.Plot(x[rng], y[rng], sc))
else
push!(gsp.plots, Gaston.Plot(x[rng], y[rng], fr, sc))
end
end
end
else
Expand Down Expand Up @@ -774,8 +778,8 @@ gaston_lc_ls_lw(series::Series, clims, i::Int) = (
)

gaston_mk_ms_mc(series::Series, clims, i::Int) = (
gaston_marker(_cycle(series[:markershape], i), get_markeralpha(series, i)),
0.2_cycle(series[:markersize], i),
gaston_marker(_getattr(series, :markershape, i), get_markeralpha(series, i)),
0.2 * _getattr(series, :markersize, i),
gaston_color(get_markercolor(series, clims, i), get_markeralpha(series, i)),
)

Expand Down
Loading
Loading