Write a plot recipe that uses other recipes to generate data for several plots

I have the following code (here is a minimal working example) in Julia:

using Plots
using LazySets
gr()

struct Data
    pos::Matrix{Float64} # Positions in an Euclidean plane
    snodes::Vector{Vector{Int64}} # Set of supernodes
    clmap::Vector{Int64} # Cluster associated to each supernode
end

function plot_supernodes(data::Data, p::Plots.Plot = plot())::Plots.Plot
    for (i, sn) in enumerate(data.snodes)
        b = [Ball2(data.pos[v, :], 0.1) for v in sn]
        chb = ConvexHullArray(b)
        plot!(p, chb, 1e-3, alpha = 0.2, color = data.clmap[i])
    end
    return p
end

pos = rand(100, 2)
snodes = [collect(i : i + 4) for i in 1:5:100]
clmap = rand(1:4, 20)

data = Data(pos, snodes, clmap)
p = plot_supernodes(data)

Now, I would like to convert the function plot_supernodes(data::Data, p::Plots.Plot) in a plot recipe that would allow me to eliminate the dependency on Plots.jl (that is the entire idea of the recipes from my understanding). This dependency is problematic since this code will be part of a package and I do not want the package to depend on Plots.jl.

I am having trouble designing such a recipe given that it must somehow call the plot recipes defined in LazySets.jl multiple times to create one single recipe that when called using plot() will plot each convex hull in a given color. I am new to using recipes and I have no idea how to accomplish this.

1 Like

Here is one way:

@recipe function f(data::Data)
    seriesalpha --> 0.2
    for (i, chb) in enumerate(ConvexHullArray.([[Ball2(data.pos[v, :], 0.1) for v in sn] for sn in data.snodes]))
        @series begin 
            color --> data.clmap[i]
            return (chb, 1e-3)
        end
    end
end

plot(data)

A good resource is How do Recipes actually work?.

3 Likes

Thank you, it worked! I will take a look at the reference that you point me to. Again, thanks!

BTW, I posted this question on SO as well. I could go and post the answer myself, but it’d be better if you posted it yourself.