Giter VIP home page Giter VIP logo

graphmakie.jl's Introduction

GraphMakie

Stable Dev Build Status Coverage

Plotting graphs¹... with Makie!

This package is just a plotting recipe, you still need to use one of the Makie backends.

GraphMakie is in an early development stage and might break often. Any contribution such as suggesting features, raising issues and opening PRs are welcome!

Starting from v0.3 GraphMakie.jl switches from LightGraphs.jl to Graphs.jl for the graph representation. See this discourse post for more information. If you want to use LightGraphs.jl please specifically ] add [email protected]!

Installation

pkg> add GraphMakie

Basic usage

using GLMakie
using GraphMakie
using Graphs
g = complete_graph(10)
graphplot(g)

¹the networky type with nodes and edges

graphmakie.jl's People

Contributors

ariguiba avatar asinghvi17 avatar behinger avatar bileamscheuvens avatar dependabot[bot] avatar fbanning avatar filchristou avatar fredcallaway avatar github-actions[bot] avatar greimel avatar hdavid16 avatar hexaeder avatar isaactay avatar jeremiahpslewis avatar maltesie avatar piever avatar pitmonticone avatar ranocha avatar simondanisch avatar thchr avatar valentinkaisermayer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphmakie.jl's Issues

Guideline on Contributions

Hey, very nice package. I've used a bit, and I'm interested in contributing. I was wondering if there are any guidelines.

Thanks.

Changing nlabels does not update the plot

Hi!

I was trying to show and hide labels using click events, but I notice that doing plt.nlabels[] = plt.nlabels[] doesn't trigger the relabeling of the nodes. Therefore, the changes on the nlabels observable appear when another action happens, for example, dragging and dropping nodes. The same code works perfectly when I change the node_colors instead of the node_labels.

Code example using GLMakie 0.5.4 and GraphMakie 0.3.3:

begin
	using Graphs
	using GLMakie, GraphMakie
end

graph = smallgraph(:karate)

begin
	node_colors = fill(:white, nv(graph))
	node_colors[1] = :lightgray
	node_colors[34] = :lightgray
end

begin
	node_labels = fill("", nv(graph))
	node_labels[1] = "Mr. Hi"
	node_labels[34] = "John A"
end

begin
	figure, axis, plt = graphplot(graph,
		node_color = node_colors,
		node_size = fill(14, nv(graph)),
		node_attr = (strokewidth = 2, strokecolor = :lightgray),
		edge_color = :lightgray,
		edge_width = fill(2, ne(graph)),
		nlabels = node_labels,
		nlabels_align = (:center, :bottom),
		nlabels_distance = 10)
	
	hidespines!(axis)
	hidedecorations!(axis)
	
	figure
end

begin
	deregister_interaction!(axis, :rectanglezoom)
	# register_interaction!(axis, :nhover, NodeHoverHighlight(plt))
	register_interaction!(axis, :ehover, EdgeHoverHighlight(plt))
	register_interaction!(axis, :ndrag, NodeDrag(plt))
	register_interaction!(axis, :edrag, EdgeDrag(plt))
end

function node_action(idx, event, axis)
	if (idx != 1) && (idx != 34)
		if plt.nlabels[][idx] == ""
    		plt.nlabels[][idx] = string(idx)
		else
			plt.nlabels[][idx] = ""
		end
	end
	plt.nlabels[] = plt.nlabels[]
end

register_interaction!(axis, :nodeclick, NodeClickHandler(node_action))

display(figure)

Using the following function, the node colors change properly:

function node_action(idx, event, axis)
	if (idx != 1) && (idx != 34)
		if plt.node_color[][idx] == :white
    		plt.node_color[][idx] = :lightgray
		else
			plt.node_color[][idx] = :white
		end
	end
	plt.node_color[] = plt.node_color[]
end

Cheers,

Problems plotting directed graphs without edges

On Julia v1.8.3 with GraphMakie v0.4.3, Makie v0.18.2, GLMakie v0.7.2 and:

using GLMakie, GraphMakie; import Graphs
graph = Graphs.SimpleDiGraph(2)

the following work as expected:

graphplot(graph)
graphplot(graph, edge_plottype = Makie.automatic)

while these do not:

graphplot(graph, edge_plottype = :linesegments)
# ERROR: MethodError: no method matching ptype(::Type{Any})

# (this is the one I actually need:)
graphplot(graph, edge_plottype = :beziersegments)
# ERROR: StackOverflowError:
# [...]
# Billboard(angles::Vector{Any}) (repeats 15393 times)
#    @ MakieCore ~/.julia/packages/MakieCore/77C6Z/src/types.jl:112

I can work around this by conditionally setting edge_plottype = Makie.automatic if the graph has no edges.

(Slightly off-topic, but graphplot(graph, edge_plottype = :somethingelse) gives a confusing error message MethodError: no method matching length(::Nothing) while it should probably complain about an invalid plot type instead.)

Simpler curvy edges

Is it possible to bend edges like below automatically? If not, would a PR be welcome?

image

let	
	function points_on_circle(n, c = Point(0, 0))
		x = range(0, 2, n + 1)
		x = x[2:end]
	
		Point2.(sinpi.(x), cospi.(x)) .+ Ref(c)
	end
	
	function rotate_vector(pt::Point2, α)
		x, y = pt
		sα, cα = sincos(α)
		Point2(x *- y * sα, x *+ y * cα)
	end

	function get_tangents(g, node_locs, α=0.1)
		map(edges(g)) do edge
			diff = node_locs[dst(edge)] - node_locs[src(edge)]
			tangents = rotate_vector.(Ref(diff), [α, -α])
		end
	end
	
	g = SimpleWeightedDiGraph([
			0 1 1;
			2 0 1;
			2 2 0
			])
	
	node_locs = points_on_circle(nv(g))
	layout = _ -> node_locs
	tangents = get_tangents(g, node_locs, 0.1)
	edge_width = weight.(edges(g))
	graphplot(g;
		tangents, layout, edge_width,
		axis = (aspect = DataAspect(), )
	)
	

end

plot a 2 vertex graph

Thanks for the amazing work on this package!

I ran into a little issue with a little graph.
A simple way to reproduce is with the basic usage example from the readme. The only modification is to create a 2 node graph instead of 10.

This is the error I get:

(jl_Zsljpy) pkg> st
      Status `C:\Users\visser_mn\AppData\Local\Temp\jl_Zsljpy\Project.toml`
  [e9467ef8] GLMakie v0.4.4
  [1ecd5474] GraphMakie v0.2.1
  [093fc24a] LightGraphs v1.3.5

julia> using GLMakie

julia> using GraphMakie

julia> using LightGraphs

julia> g = complete_graph(2)
{2, 1} undirected simple Int64 graph

julia> graphplot(g)
ERROR: MethodError: no method matching repeat(::Float64; inner=2)
Closest candidates are:
  repeat(::AbstractArray; inner, outer) at abstractarraymath.jl:276
  repeat(::AbstractArray, ::Any...) at abstractarraymath.jl:239 got unsupported keyword argument "inner"
  repeat(::Char, ::Integer) at strings/string.jl:334 got unsupported keyword argument "inner"
  ...
Stacktrace:
  [1] (::GraphMakie.var"#10#30")(arg1#275::Float64)
    @ GraphMakie .\none:0
  [2] lift(::Function, ::Observable{Any}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Makie C:\Users\visser_mn\.julia\packages\Makie\xbI6d\src\interaction\nodes.jl:13
  [3] lift(::Function, ::Observable{Any})
    @ Makie C:\Users\visser_mn\.julia\packages\Makie\xbI6d\src\interaction\nodes.jl:10
  [4] plot!(gp::Combined{GraphMakie.graphplot, Tuple{SimpleGraph{Int64}}})
    @ GraphMakie C:\Users\visser_mn\.julia\packages\GraphMakie\aHBXB\src\recipes.jl:134
  [5] plot!(scene::Scene, P::Type{Combined{GraphMakie.graphplot, Tuple{SimpleGraph{Int64}}}}, attributes::Attributes, input::Tuple{Observable{SimpleGraph{Int64}}}, args::Observable{Tuple{SimpleGraph{Int64}}})
    @ Makie C:\Users\visser_mn\.julia\packages\Makie\xbI6d\src\interfaces.jl:428
  [6] plot!(scene::Scene, P::Type{Combined{GraphMakie.graphplot}}, attributes::Attributes, args::SimpleGraph{Int64}; kw_attributes::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:show_axis,), Tuple{Bool}}})
    @ Makie C:\Users\visser_mn\.julia\packages\Makie\xbI6d\src\interfaces.jl:339
  [7] plot(P::Type{Combined{GraphMakie.graphplot}}, args::SimpleGraph{Int64}; axis::NamedTuple{(), Tuple{}}, figure::NamedTuple{(), Tuple{}}, kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Makie C:\Users\visser_mn\.julia\packages\Makie\xbI6d\src\figureplotting.jl:28
  [8] plot
    @ C:\Users\visser_mn\.julia\packages\Makie\xbI6d\src\figureplotting.jl:18 [inlined]
  [9] graphplot(args::SimpleGraph{Int64}; attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ GraphMakie C:\Users\visser_mn\.julia\packages\MakieCore\S8PkO\src\recipes.jl:31
 [10] graphplot(args::SimpleGraph{Int64})
    @ GraphMakie C:\Users\visser_mn\.julia\packages\MakieCore\S8PkO\src\recipes.jl:31
 [11] top-level scope
    @ REPL[8]:1

A 1 node graph works without error, though I don't see a single dot on the graph.

Feature Request: tree-structured regression and classification models

I'm trying to visualize a decision tree. The interpretable ML book has a nice visualization for it:

library("partykit")
set.seed(42)
n = 100
dat_sim = data.frame(feature_x1 = rep(c(3,3,4,4), times = n), feature_x2 = rep(c(1,2,2,2), times = n), y = rep(c(1, 2, 3, 4), times = n))
dat_sim = dat_sim[sample(1:nrow(dat_sim), size = 0.9 * nrow(dat_sim)), ]
dat_sim$y = dat_sim$y + rnorm(nrow(dat_sim), sd = 0.2)
ct = ctree(y ~ feature_x1 + feature_x2, dat_sim)
plot(ct, inner_panel = node_inner(ct, pval = FALSE, id = FALSE),
  terminal_panel = node_boxplot(ct, id = FALSE))

image

Maybe this would be a nice feature for GraphMakie as well

interface `edge_paths` of the recipe to user

Hi,

I want to highlight some edges and I find it hard to recalculate the Vector{AbstractPath}
What I want to do is the following:

gc = circular_ladder_graph(5) |> DiGraph
f,a,p = graphplot(gc, elabels = repr.(edges(gc)), nlabels=repr.(vertices(gc)))
edgeplot!(a, p.edge_paths[][4:9], linewidth=15, color=(:red,0.5))

which will draw the following:
image

It's fairly easy when edge_paths is given available to the user.

Otherwise I must call find_edge_paths which also expects some Attributes value, which is rather complicated.
Is there a more sophisticated way?

Text boxes instead of text labels

I'm using GraphMakie to plot trees. Basically I get what I want, but the text labels on the nodes don't really look good, because they get plotted underneath the edges (or the node markers):
tree

I would like to have some rectangles around the text labels and the edges attaching to these rectangles. More like this:
Skizzen - Frame 1

How can I achieve this using GraphMakie?

Julia 1.3 support

It looks like this line: https://github.com/JuliaPlots/GraphMakie.jl/blob/649f1aec493bc57fdd3ca66e57d6b5eaaf946af4/src/beziercurves.jl#L55
is using syntax introduced in Julia 1.4:
https://github.com/JuliaLang/julia/blob/master/HISTORY.md#new-language-features-3

It seems like in general Makie supports Julia 1.3:
https://github.com/JuliaPlots/Makie.jl/blob/2faa3d75733689f2d3e802b1f623d0f90343005a/Project.toml#L91

We are using GraphMakie as a backend in our new tensor network visualization backend in ITensors.jl. Generally we try to support Julia 1.3 so I think it would be nice if GraphMakie did as well.

Failure to remove edges when updating observable to graph with no edges

Thanks for this really nice package!

I'm having some issues with the updateability. I'm calling graphplot(g::Observable{SimpleDiGraph}) and I've noticed that when g changes to a graph with no edges, the recipe does not remove the extra edges automatically (or rather, it does, but I need to refresh the page to see the update).

MWE:

using Graphs, GraphMakie, WGLMakie
g = Observable(complete_digraph(10))
graphplot(g) # graph is rendered correctly
g[] = complete_digraph(5) # graph updates correctly
g[] = SimpleDiGraph(5) # graph with no edges: edges are not removed unless I refresh the page

add reference tests based on examples in docs

as of now, one has to manually check the preview docs for a PR to see wether everything works

I think it would be good to automate this process (reference testing for all of the plots in the docs)

rework docs before new release

  • show some 3D plots
  • make use of different NetworkLayout.jl layouts
  • show better examples for labels
  • show arrows on directed graphs

:colormap not found when using `node_attr`

When I try to add a Colorbar, the :colormap key is not found if I use the node_attr.
With the edge_attr it works as expected.

using Graphs, GraphMakie, CairoMakie
gr = erdos_renyi(9, 16, seed=1)
begin
	local bcentr = betweenness_centrality(gr)
	local bcentrsize = 10 .+ 20 .* bcentr
	local ft, at, pt = graphplot(gr;
		nlabels=repr.(vertices(gr)),
		node_size=bcentrsize,
		node_attr = (colormap = :thermal, color = bcentr, colorrange=(min(bcentr...), max(bcentr...))))
	at.title = "Betweenness Centrality";
	ft[2,1] = Colorbar(ft, pt.plots[1], label = "Betweeness Centrality", vertical=false)
	ft
end
KeyError: key :colormap not found
    getindex(::Dict{Symbol, Observables.Observable}, ::Symbol)@dict.jl:481
    [email protected]:96[inlined]
    getindex(::MakieCore.Combined{GraphMakie.edgeplot, Tuple{Vector{GraphMakie.Line{GeometryBasics.Point{2, Float32}}}}}, ::Symbol)@attributes.jl:192
    [email protected]:83[inlined]
    var"#layoutable#458"(::Base.Pairs{Symbol, Any, Tuple{Symbol, Symbol}, NamedTuple{(:label, :vertical), Tuple{String, Bool}}}, ::typeof(Makie.MakieLayout.layoutable), ::Type{Makie.MakieLayout.Colorbar}, ::Makie.Figure, ::MakieCore.Combined{GraphMakie.edgeplot, Tuple{Vector{GraphMakie.Line{GeometryBasics.Point{2, Float32}}}}})@colorbar.jl:9
    #_layoutable#[email protected]:69[inlined]
    #_#[email protected]:49[inlined]
    top-level scope@Local: 9[inlined]

But when I add the colormap in the edge_attr as a workaround it works normally:

begin
	local bcentr = betweenness_centrality(gr)
	local bcentrsize = 10 .+ 20 .* bcentr
	local ft, at, pt = graphplot(gr;
		nlabels=repr.(vertices(gr)),
		node_size=bcentrsize,
		node_attr = (colormap = :thermal, color = bcentr, colorrange=(min(bcentr...), max(bcentr...))),
		edge_attr = (colormap = :thermal, color = :black, colorrange=(min(bcentr...), max(bcentr...))))
	at.title = "Betweenness Centrality";
	ft[2,1] = Colorbar(ft, pt.plots[1], label = "Betweeness Centrality", vertical=false)
	ft
end

image

`tangents` and `waypoints` support for self-loops

It seems that tangents does not apply to selfedges. What are your thoughts on applying it to these? This way, tangents would apply to all edge types and we wouldn't need the selfedge_direction attribute. The selfedge_direction has a major drawback: you can only specify the direction going out of the node, but not the direction coming into the node.

We could also support other attributes like waypoints for selfedges.

Feature request: `arrow_shift = 1` land arrow on the surface of the node marker

It would be great to be able to set the arrow shift parameter to 1 and have the tip of the arrow land on the edge (surface) of the node, not on the center of the node. This would be the preferred behavior. This will require taking into account the size of the marker.

The current work around is to pass a vector of arrow shifts to try to get them to land on the surface of each node (requires some trial and error).

Example in docs throws error

using GLMakie, GraphMakie, LightGraphs

GLMakie.activate!()

g = wheel_graph(10)
f, ax, p = graphplot(g)
hidedecorations!(ax)
hidespines!(ax)
ax.aspect = DataAspect()

Throws:

ERROR: LoadError: MethodError: no method matching ne(::SimpleGraph{Int64})
Closest candidates are:
  ne(::Graphs.SimpleGraphs.AbstractSimpleGraph) at ~/.julia/packages/Graphs/Mih78/src/SimpleGraphs/SimpleGraphs.jl:118
  ne(::Graphs.AbstractGraph) at ~/.julia/packages/Graphs/Mih78/src/interface.jl:158
Stacktrace:
  [1-10]  internal
       @ GraphMakie, Makie, Unknown
    [11] include(fname::String)
       @ Base.MainInclude ./client.jl:451
Use `err` to retrieve the full stack trace.
in expression starting at [path]:7

Package status:

pkg> st
      Status `~/node-size/Project.toml`
  [e9467ef8] GLMakie v0.4.7
  [1ecd5474] GraphMakie v0.3.0
  [093fc24a] LightGraphs v1.3.5

Julia version: 1.7.0 (2021-11-30)

Unable to make animation using GraphMakie

I want to create a simple animation where the colour of the nodes in a graph change. I have tried adapting the Makie animation tutorial, but it does not seem to work for graphs. This is the example:

# Fetch packages
using Pkg; Pkg.activate(".");
using Makie
using GLMakie
using GraphMakie
using Graphs
using Makie.Colors

# Create a line animation, where the line's color changes (works).
fig_line, ax_line, plot_line = lines(0..10, sin; linewidth=10)
function change_function_line(frame)
    plot_line.color = HSV(frame, 1, 0.75)
end
record(change_function_line, fig_line, "color_animation_line.mp4", range(0,360, length=30); framerate=3)


# Create a graph animation, where the graphs's color changes (does not work, the colors stay static throughout the animation).
fig_graph, ax_graph, plot_graph = GraphMakie.graphplot(path_graph(10),node_color=rand(RGB,10),node_size=40,edge_size=1)
function change_function_graph(frame)
    plot_graph.node_color[][:] = rand(RGB,10)
end
record(change_function_graph, fig_graph, "color_animation_graph.mp4", range(0,360, length=30); framerate=3)

# Check whenever changing graph color is possible:
fig_graph                                   # Check the colors of the graph.
plot_graph.node_color[][:] = rand(RGB,10);  # Chanegs the colors of the graph.
fig_graph                                   # Check the colors of the graph. It is different.

I am also uploading the two animations:
https://user-images.githubusercontent.com/18099310/191730460-bcd88fec-4194-44a2-8552-6df4db56ce02.mp4
https://user-images.githubusercontent.com/18099310/191730463-b6621331-9f39-4a3a-a492-eea4ad357a33.mp4
And the graph before and after I change its colour:
image
image

Giving in elabels_rotation as Real throws error

gc = circular_ladder_graph(5)
graphplot(gc, elabels = repr.(edges(gc)), nlabels=repr.(vertices(gc)), elabels_rotation=45)
ERROR: TypeError: in new, expected Makie.ScalarOrVector{Quaternionf}, got a value of type Makie.ScalarOrVector{Int64}
Stacktrace:
  [1] Makie.GlyphCollection(glyphs::Vector{Char}, fonts::Vector{FreeTypeAbstraction.FTFont}, origins::Vector{Point{3, Float32}}, extents::Vector{FreeTypeAbstraction.FontExtent{Float32}}, scales::Vector{Vec{2, Float32}}, rotations::Vector{Int64}, colors::Vector{ColorTypes.RGBA{Float32}}, strokecolors::Vector{ColorTypes.RGBA{Float32}}, strokewidths::Vector{Int64})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/types.jl:342
  [2] glyph_collection(str::String, font_per_char::Base.Generator{String, Makie.var"#662#663"{FreeTypeAbstraction.FTFont}}, fontscale_px::Base.Generator{String, Makie.var"#660#661"{Float32}}, halign::Symbol, valign::Symbol, lineheight_factor::Float64, justification::MakieCore.Automatic, rotation::Int64, color::ColorTypes.RGBA{Float32}, strokecolor::ColorTypes.RGBA{Float32}, strokewidth::Int64)
    @ Makie ~/.julia/packages/Makie/gQOQF/src/layouting/layouting.jl:213
  [3] layout_text
    @ ~/.julia/packages/Makie/gQOQF/src/layouting/layouting.jl:53 [inlined]
  [4] (::Makie.var"#981#983"{Vector{Makie.GlyphCollection}})(str::String, ts::Float32, f::FreeTypeAbstraction.FTFont, al::Tuple{Symbol, Symbol}, rot::Int64, jus::MakieCore.Automatic, lh::Float64, col::ColorTypes.RGBA{Float32}, scol::ColorTypes.RGBA{Float32}, swi::Int64)
    @ Makie ~/.julia/packages/Makie/gQOQF/src/basic_recipes/text.jl:47
  [5] broadcast_foreach(::Function, ::Vector{String}, ::Vararg{Any})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/utilities/utilities.jl:176
  [6] (::Makie.var"#980#982"{Observable{Any}, Observable{Any}, Observable{Vector{Makie.GlyphCollection}}})(str::Vector{String}, ts::Int64, pos::Vector{Point{2, Float32}}, f::String, al::Tuple{Symbol, Symbol}, rot::Int64, jus::MakieCore.Automatic, lh::Float64, col::Symbol, scol::Tuple{Symbol, Float64}, swi::Int64)
    @ Makie ~/.julia/packages/Makie/gQOQF/src/basic_recipes/text.jl:45
  [7] (::Observables.OnUpdate{Makie.var"#980#982"{Observable{Any}, Observable{Any}, Observable{Vector{Makie.GlyphCollection}}}, Tuple{Observable{Vector{String}}, Observable{Any}, Observable{Any}, Observable{Any}, Observable{Any}, Observable{Any}, Observable{Any}, Observable{Any}, Observable{Any}, Observable{Any}, Observable{Any}}})(#unused#::Vector{String})
    @ Observables ~/.julia/packages/Observables/OFj0u/src/Observables.jl:334
  [8] #invokelatest#2
    @ ./essentials.jl:716 [inlined]
  [9] invokelatest
    @ ./essentials.jl:714 [inlined]
 [10] notify(observable::Observable{Vector{String}})
    @ Observables ~/.julia/packages/Observables/OFj0u/src/Observables.jl:88
 [11] plot!(plot::MakieCore.Text{Tuple{Vector{String}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/basic_recipes/text.jl:56
 [12] plot!(scene::Combined{GraphMakie.graphplot, Tuple{SimpleGraph{Int64}}}, P::Type{MakieCore.Text{Tuple{Vector{String}}}}, attributes::Attributes, input::Tuple{Observable{Any}}, args::Observable{Tuple{Vector{String}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:456
 [13] plot!(scene::Combined{GraphMakie.graphplot, Tuple{SimpleGraph{Int64}}}, P::Type{MakieCore.Text}, attributes::Attributes, args::Observable{Any}; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:339
 [14] plot!
    @ ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:308 [inlined]
 [15] #plot!#157
    @ ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:291 [inlined]
 [16] text!(::Combined{GraphMakie.graphplot, Tuple{SimpleGraph{Int64}}}, ::Vararg{Any}; attributes::Base.Pairs{Symbol, Observable, NTuple{6, Symbol}, NamedTuple{(:position, :rotation, :offset, :align, :color, :textsize), Tuple{Observable{Vector{Point{2, Float32}}}, Observable{Int64}, Observable{Vector{Point{2, Float32}}}, Observable{Any}, Observable{Any}, Observable{Any}}}})
    @ MakieCore ~/.julia/packages/MakieCore/S8PkO/src/recipes.jl:35
 [17] plot!(gp::Combined{GraphMakie.graphplot, Tuple{SimpleGraph{Int64}}})
    @ GraphMakie ~/.julia/packages/GraphMakie/ya5tg/src/recipes.jl:309
 [18] plot!(scene::Scene, P::Type{Combined{GraphMakie.graphplot, Tuple{SimpleGraph{Int64}}}}, attributes::Attributes, input::Tuple{Observable{SimpleGraph{Int64}}}, args::Observable{Tuple{SimpleGraph{Int64}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:428
 [19] plot!(scene::Scene, P::Type{Combined{GraphMakie.graphplot}}, attributes::Attributes, args::SimpleGraph{Int64}; kw_attributes::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:show_axis,), Tuple{Bool}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:339
 [20] plot(P::Type{Combined{GraphMakie.graphplot}}, args::SimpleGraph{Int64}; axis::NamedTuple{(), Tuple{}}, figure::NamedTuple{(), Tuple{}}, kw_attributes::Base.Pairs{Symbol, Any, Tuple{Symbol, Symbol, Symbol}, NamedTuple{(:elabels, :nlabels, :elabels_rotation), Tuple{Vector{String}, Vector{String}, Int64}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/figureplotting.jl:28
 [21] #graphplot#13
    @ ~/.julia/packages/MakieCore/S8PkO/src/recipes.jl:31 [inlined]
 [22] top-level scope
    @ REPL[16]:1

I would expect from here that such input should be handled.
A workaround would be to substitute rot = $(gp.elabels_rotation) with something like rot = Vector{Float32}(fill($(gp.elabels_rotation), ne(gp.graph[])). This would also encourage to have elabels_opposite being applied to all input elabels_rotation rather just give out a fixed rotation based on the vertices position, as mentioned on #67

Passing in elabels_opposite will not influence the result. In my opinion this shouldn't be the case and I would propose to move the relative for loop outside the if-else statement. But this would mean that the "opposite" applies to the rotations handled in and it doesn't give out a particular opposite angle as it is now.

From the other side maybe using Vector{Float32} is not very generic ?

`graphplot` stackoverflow

given the trace bottoms out at PNGFiles, it may be that the issue is better suited over there.

mwe

using LightGraphs, GLMakie, GraphMakie
g = path_graph(6)
graphplot(g)

trace

julia> graphplot(g)

signal (11): Segmentation fault: 11
in expression starting at none:0
_buffer_color_type at /Users/anand/.julia/packages/PNGFiles/yn5z5/src/io.jl:0
#_load#6 at /Users/anand/.julia/packages/PNGFiles/yn5z5/src/io.jl:148
_load##kw at /Users/anand/.julia/packages/PNGFiles/yn5z5/src/io.jl:81 [inlined]
#load#2 at /Users/anand/.julia/packages/PNGFiles/yn5z5/src/io.jl:28
load at /Users/anand/.julia/packages/PNGFiles/yn5z5/src/io.jl:23
jl_apply_generic at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.7.dylib (unknown line)
jl_f__call_latest at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.7.dylib (unknown line)
#invokelatest#2 at ./essentials.jl:716 [inlined]
invokelatest at ./essentials.jl:714 [inlined]
#load#3 at /Users/anand/.julia/packages/ImageIO/6h74I/src/ImageIO.jl:53
load at /Users/anand/.julia/packages/ImageIO/6h74I/src/ImageIO.jl:53
unknown function (ip: 0x12f296aa3)
jl_apply_generic at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.7.dylib (unknown line)
jl_f__call_latest at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.7.dylib (unknown line)
#invokelatest#2 at ./essentials.jl:716 [inlined]
invokelatest at ./essentials.jl:714 [inlined]
#action#33 at /Users/anand/.julia/packages/FileIO/DNKwN/src/loadsave.jl:219
action at /Users/anand/.julia/packages/FileIO/DNKwN/src/loadsave.jl:197 [inlined]
#action#32 at /Users/anand/.julia/packages/FileIO/DNKwN/src/loadsave.jl:185
action at /Users/anand/.julia/packages/FileIO/DNKwN/src/loadsave.jl:185 [inlined]
#load#14 at /Users/anand/.julia/packages/FileIO/DNKwN/src/loadsave.jl:113
load at /Users/anand/.julia/packages/FileIO/DNKwN/src/loadsave.jl:110 [inlined]
_broadcast_getindex_evalf at ./broadcast.jl:670 [inlined]
_broadcast_getindex at ./broadcast.jl:643 [inlined]
getindex at ./broadcast.jl:597 [inlined]
copy at ./broadcast.jl:943 [inlined]
materialize at ./broadcast.jl:904 [inlined]
icon at /Users/anand/.julia/packages/Makie/PFSZS/src/Makie.jl:254
unknown function (ip: 0x12f2935cb)
#Screen#48 at /Users/anand/.julia/packages/GLMakie/TViqo/src/screen.jl:346
Screen at /Users/anand/.julia/packages/GLMakie/TViqo/src/screen.jl:301 [inlined]
global_gl_screen at /Users/anand/.julia/packages/GLMakie/TViqo/src/screen.jl:247 [inlined]
global_gl_screen at /Users/anand/.julia/packages/GLMakie/TViqo/src/screen.jl:394
global_gl_screen at /Users/anand/.julia/packages/GLMakie/TViqo/src/screen.jl:393 [inlined]
backend_display at /Users/anand/.julia/packages/GLMakie/TViqo/src/display.jl:2 [inlined]
#display#903 at /Users/anand/.julia/packages/Makie/PFSZS/src/display.jl:60
display at /Users/anand/.julia/packages/Makie/PFSZS/src/display.jl:56 [inlined]
#display#902 at /Users/anand/.julia/packages/Makie/PFSZS/src/display.jl:52 [inlined]
display at /Users/anand/.julia/packages/Makie/PFSZS/src/display.jl:52 [inlined]
#display#901 at /Users/anand/.julia/packages/Makie/PFSZS/src/display.jl:51 [inlined]
display at /Users/anand/.julia/packages/Makie/PFSZS/src/display.jl:51
unknown function (ip: 0x12f28cca7)
jl_apply_generic at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.7.dylib (unknown line)
jl_f__call_latest at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.7.dylib (unknown line)
print_response at /Users/sabae/src/julia/usr/share/julia/stdlib/v1.7/REPL/src/REPL.jl:0
#45 at /Users/sabae/src/julia/usr/share/julia/stdlib/v1.7/REPL/src/REPL.jl:275
jfptr_YY.45_47516 at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)
jl_apply_generic at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.7.dylib (unknown line)
with_repl_linfo at /Users/sabae/src/julia/usr/share/julia/stdlib/v1.7/REPL/src/REPL.jl:508
jl_apply_generic at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.7.dylib (unknown line)
print_response at /Users/sabae/src/julia/usr/share/julia/stdlib/v1.7/REPL/src/REPL.jl:273
do_respond at /Users/sabae/src/julia/usr/share/julia/stdlib/v1.7/REPL/src/REPL.jl:844
unknown function (ip: 0x12f0892af)
jl_apply_generic at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.7.dylib (unknown line)
jl_f__call_latest at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.7.dylib (unknown line)
#invokelatest#2 at ./essentials.jl:716 [inlined]
invokelatest at ./essentials.jl:714 [inlined]
run_interface at /Users/sabae/src/julia/usr/share/julia/stdlib/v1.7/REPL/src/LineEdit.jl:2493
jfptr_run_interface_45833 at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)
jl_apply_generic at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.7.dylib (unknown line)
run_frontend at /Users/sabae/src/julia/usr/share/julia/stdlib/v1.7/REPL/src/REPL.jl:1230
#49 at ./task.jl:411
jfptr_YY.49_47569 at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)
jl_apply_generic at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.7.dylib (unknown line)
start_task at /Applications/Julia-1.7.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.7.dylib (unknown line)
Allocations: 163411446 (Pool: 163374169; Big: 37277); GC: 100

env info

(jl_Mcs5Kg) pkg> add GLMakie, GraphMakie, LightGraphs
  [e9467ef8] + GLMakie v0.4.6
  [1ecd5474] + GraphMakie v0.2.4
  [093fc24a] + LightGraphs v1.3.5

julia> versioninfo()
Julia Version 1.7.0-rc1
Commit 9eade6195e (2021-09-12 06:45 UTC)
Platform Info:
  OS: macOS (arm64-apple-darwin20.5.0)
  CPU: Apple M1
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-12.0.1 (ORCJIT, cyclone)
Environment:
  JULIA_NUM_THREADS = 8

Edge labels orientation

Currently when plotting a graph, the edge labels are having by default a direction from lower vertex to higher, thus sometimes text appears upside down:

using Graphs
gc = circular_ladder_graph(5)
graphplot(gc, elabels = repr.(edges(gc)), nlabels=repr.(vertices(gc)))

image

Locally I am using a wrapper to output labels in a more readable way:
image

Would you be interested in a PR to make that the default behavior ?

error if layout returns `Vector{Vector{T}}`

using Pkg
Pkg.activate(temp=true)
Pkg.add("GLMakie")
Pkg.add("GraphMakie")
Pkg.add("LightGraphs")

using GLMakie
using GraphMakie
using LightGraphs

g = complete_graph(3)
pos1 = [(0,0),
        (1,1),
        (0,1)]

pos2 = [[0,0],
        [1,1],
        [0,1]]
 
graphplot(g; layout=(x)->pos1) #works
graphplot(g; layout=(x)->pos2) #conversion to Point2 fails

How to add annotations to edges of a SimpleDiGraph?

I have a SimpleDiGraph that I want to add the name of each edge on, but I don't know how I can do that. This is my SimpleDiGraph plot:

using Graphs, CairoMakie, GraphMakie

graph = SimpleDiGraph(4)
nodes = ["Q1", "Q2", "Q3", "Q4"]
# edges = [(1, 2), (1, 3), (1, 4), (1, 1), ..., (4, 4)]
for edge in edges
    add_edge!(graph, edge[1], edge[2])
end

graphplot(
    graph,
    names=nodes
)

image

Suppose I want to add arbitrary numbers as annotations on edges. How can I do that?

interactions broken on new Makie

I saw that #80 addd Makie 0.17 support. However it seems that with Makie 0.17 the interaction examples from http://juliaplots.org/GraphMakie.jl/dev/generated/interactions/ don't work anymore.

This is the code I use, identical to the docs except for using GLMakie, and adding a log statement to the event handlers.

# ] add GLMakie GraphMakie Graphs Colors
# [5ae59095] Colors v0.12.8
# [e9467ef8] GLMakie v0.6.3
# [1ecd5474] GraphMakie v0.3.5
# [86223c79] Graphs v1.7.0

using GLMakie
using GraphMakie
using Graphs
using Colors

g = wheel_graph(10)
f, ax, p = graphplot(g,
                     edge_width = [2.0 for i in 1:ne(g)],
                     edge_color = [colorant"gray" for i in 1:ne(g)],
                     node_size = [10 for i in 1:nv(g)],
                     node_color = [colorant"red" for i in 1:nv(g)])
hidedecorations!(ax); hidespines!(ax)
ax.aspect = DataAspect()

deregister_interaction!(ax, :rectanglezoom)

# node click interaction
function node_click_action(idx, args...)
    @info "node_click_action" idx
    p.node_color[][idx] = rand(RGB)
    p.node_color[] = p.node_color[]
end
nclick = NodeClickHandler(node_click_action)
register_interaction!(ax, :nclick, nclick)

# hover interaction
function node_hover_action(state, idx, event, axis)
    @info "node_hover_action" idx
    p.node_size[][idx] = state ? 20 : 10
    p.node_size[] = p.node_size[] # trigger observable
end
nhover = NodeHoverHandler(node_hover_action)
register_interaction!(ax, :nhover, nhover)

f

If I then downgrade to the previous GraphMakie, v0.3.4, which brings along GLMakie v0.5.5, the interactions work again.

Plotting a graph with given node positions

As far as I understood, GraphMakie provides the graphplot recipe which is a neat wrapper that (among other things) plots nodes as scatterpoints and edges as linesegments. Now I do have a SimpleDiGraph and a Vector{Point2{Float64}} determining the position for each node in the graph. I can of course easily use this vector to create a scatterplot. I can also use the graph to create a graphplot showing the nodes and edges. So far, so good! :)

However, I fail to see how to connect those two and create a graph plot with predetermined node positions (i.e. without using any of the layouting algorithms). For the past hours I've tried to understand how to write a custom layout for NetworkLayout.jl because I thought that this is what I need to do but it didn't work out. Most likely, I'm just misunderstanding its interface and am approaching this in a wrong way.

Can you help me understand if what I'm trying to do is actually feasible with GraphMakie? (I sure hope so!) If yes, can you point me in the right direction of what I need to do?

Edge linestyles not always working

tl;dr: Using edge_attr = (; linestyle = [...]) requires setting edge_plottype = :beziersegments too.

I was trying to use the linestyle edge attribute to represent edge types, but passing a Vector{Symbol} of line styles per edge sometimes caused plotting to fail:

ERROR: LoadError: MethodError: no method matching *(::Symbol, ::Float64)
[...]
Stacktrace:
  [1] _broadcast_getindex_evalf
    @ ./broadcast.jl:670 [inlined]
  [2] _broadcast_getindex
    @ ./broadcast.jl:643 [inlined]
  [3] getindex
    @ ./broadcast.jl:597 [inlined]
  [4] copy
    @ ./broadcast.jl:899 [inlined]
  [5] materialize(bc::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Nothing, typeof(*), Tuple{Vector{Symbol}, Float64}})
    @ Base.Broadcast ./broadcast.jl:860
  [6] (::GLMakie.var"#189#190"{GLMakie.Screen{GLFW.Window}, Makie.Scene, MakieCore.LineSegments{Tuple{Vector{GeometryBasics.Point{2, Float32}}}}})(gl_attributes::Dict{Symbol, Any})
    @ GLMakie ~/.julia/packages/GLMakie/x68HK/src/drawing_primitives.jl:278
[...]

After investigating, I noticed that this only happens if there are no double- or self-edges in the graph. The reason is that in these cases (or if the graph is too large), edge_plottype = Makie.automatic makes GraphMakie choose Makie.linesegments! to plot the edges, which interprets the Vector as defining a single linestyle pattern to be used for all the edges. (That behavior is undocumented for Makie.linesegments, though the Makie.lines documentation has an example.) The GraphMakie beziersegments! recipe, on the other hand, works as expected because it lifts the properties itself. Therefore, a workaround (for smaller graphs) is to explicitly set edge_plottype = :beziersegments.

Example:

using GraphMakie, GLMakie, Graphs

graphplot(
    DiGraph([Edge(1 => 2), Edge(2 => 1)]),
    edge_attr = (; linestyle = [:dot, :dash]),
)
# works

graphplot(
    DiGraph([Edge(1 => 2), Edge(2 => 3)]),
    edge_attr = (; linestyle = [:dot, :dash]),
)
# MethodError: no method matching *(::Symbol, ::Float64)

graphplot(
    DiGraph([Edge(1 => 2), Edge(2 => 3)]),
    edge_attr = (; linestyle = [:dot, :dash]),
    edge_plottype = :beziersegments,
)
# works

Conversely, using the Float64[] linestyle variant (defining a custom pattern) works in the :linesegments case, while for :beziersegments it depends on the number of nodes in the graph: if the pattern length is equal to Graphs.nv, the error is "Pattern needs to be a Vector of floats. Found: Float64", otherwise it seems to work.

This is not strictly a bug, because nothing promises that this should work (so feel free to close this), but I wanted to file this anyway because the behavior surprised me and it took me a while to understand what's going on.

My preferred solution would be Makie.linesegments accepting a vector of linestyles, but otherwise maybe GraphMakie should plot individual Makie.lines and lift the properties like in the bezier case to ensure consistency?

MethodError: no method matching getindex(::MakieCore.Attributes) when using `edge_attr`, `node_attr` in Makie 0.16.1

I tried using the compatibility branch in order test GraphMakie together with GeoMakie v0.3.0, and I realized some of my plots stopped working.

Following the status of my environement:

  [13f3f980] CairoMakie v0.7.0
  [1ecd5474] GraphMakie v0.3.0 `https://github.com/JuliaPlots/GraphMakie.jl.git#compathelper/new_version/2022-01-08-00-39-37-422-00161005115`
  [86223c79] Graphs v1.5.1
  [626554b9] MetaGraphs v0.7.1

I tried doing

using GraphMakie, CairoMakie, Graphs, MetaGraphs
gr = erdos_renyi(9, 16, seed=1)
begin
	local bcentr = betweenness_centrality(gr)
	local bcentrsize = 10 .+ 20 .* bcentr
	local ft, at, pt = graphplot(gr;
		nlabels=repr.(vertices(gr)),
		node_size=bcentrsize,
		node_attr = (colormap = :thermal, color = bcentr, colorrange=(min(bcentr...), max(bcentr...))),
		edge_attr = (colormap = :thermal, color = :black, colorrange=(min(bcentr...), max(bcentr...))))
	at.title = "Betweenness Centrality";
	ft[2,1] = Colorbar(ft, pt.plots[1], label = "Betweeness Centrality", vertical=false)
	ft
end

getting the error:

MethodError: no method matching getindex(::MakieCore.Attributes)

Closest candidates are:

getindex(::MakieCore.Attributes, !Matched::Symbol) at ~/.julia/packages/MakieCore/A0hGm/src/attributes.jl:95

getindex(::Union{MakieCore.Attributes, MakieCore.AbstractPlot}, !Matched::Symbol, !Matched::Symbol, !Matched::Symbol...) at ~/.julia/packages/MakieCore/A0hGm/src/attributes.jl:198

    (::Makie.MakieLayout.var"#325#333"{MakieCore.Attributes})(::Symbol)@axis.jl:625
    mapfilter(::Makie.MakieLayout.var"#325#333"{MakieCore.Attributes}, ::typeof(push!), ::Base.KeySet{Symbol, Dict{Symbol, Observables.Observable}}, ::Set{Symbol})@abstractset.jl:444
    [email protected]:436[inlined]
    add_cycle_attributes!(::MakieCore.Attributes, ::Type, ::Makie.MakieLayout.Cycle, ::Makie.MakieLayout.Cycler, ::MakieCore.Attributes)@axis.jl:624
    var"#plot!#339"(::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, ::typeof(MakieCore.plot!), ::Makie.MakieLayout.Axis, ::Type{MakieCore.Combined{GraphMakie.graphplot}}, ::MakieCore.Attributes, ::Graphs.SimpleGraphs.SimpleGraph{Int64})@axis.jl:687
    [email protected]:684[inlined]
    var"#plot#964"(::NamedTuple{(), Tuple{}}, ::NamedTuple{(), Tuple{}}, ::Base.Pairs{Symbol, Any, NTuple{4, Symbol}, NamedTuple{(:nlabels, :node_size, :node_attr, :edge_attr), Tuple{Vector{String}, Vector{Float64}, NamedTuple{(:colormap, :color, :colorrange), Tuple{Symbol, Vector{Float64}, Tuple{Float64, Float64}}}, NamedTuple{(:colormap, :color, :colorrange), Tuple{Symbol, Symbol, Tuple{Float64, Float64}}}}}}, ::typeof(MakieCore.plot), ::Type{MakieCore.Combined{GraphMakie.graphplot}}, ::Graphs.SimpleGraphs.SimpleGraph{Int64})@figureplotting.jl:39
    #graphplot#[email protected]:33[inlined]
    top-level scope@Local: 4[inlined]

The code worked normally for GraphMakie#master where the only difference is:

diff --git a/Project.toml b/Project.toml
index 87bfa78..1942769 100644
--- a/Project.toml
+++ b/Project.toml
@@ -14,7 +14,7 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
 [compat]
 GeometryBasics = "0.4"
 Graphs = "1.4"
-Makie = "0.15"
+Makie = "0.15, 0.16"
 NetworkLayout = "0.4.3"
 StaticArrays = "1.2"
 julia = "1"

reset camera view

Hi,
I'm using this package in Pluto notebook and it works very well with the WGLMakie backend. It is very easy though to accidentally select some rectangular area, zoom in, and then you have a hard time recentering the view. Maybe some button could be displayed to reset the camera?

How to handle errors due to changing the underlying graph with node/edge properties given as vectors?

I am trying to build a small app which supports user add/remove nodes and edges, or loading new graphs from somewhere else. Some node and edge properties are given as vectors. Meanwhile, I do not want to re-plot such that will invalidate all my controls (Sliders and Toggles).

In the docstring of graphplot recipe, it states that

Most of the arguments can be either given as a vector of length of the edges/nodes or as a single value. One might run into errors when changing the underlying graph and therefore changing the number of Edges/Nodes.

Does it mean I will encounter such errors when I change the underlying graphs. Indeed, when I simply do

p[:graph] = new_graph_with_different_number_of_nodes_edges

GraphMakie emits errors. I notice that these errors are mainly caused by lines below

disc = [Observable{Vector{PT}}() for i in 1:N]

update_discretized!(disc, p[:paths][]) # first call to initialize
on(p[:paths]) do paths # update if pathes change
    update_discretized!(disc, paths)
end

It seems that disc is not an Observable (N is not). Therefore, when p[:paths] updates, disc is still the old one, thus its length is wrong.

Is there any simple way to avoid such errors? Or GraphMakie has to be rewritten in a fundamental way to support my use case?

Feature request: multiple arrowheads along the edge of a directed arc

This might be something interesting to have at some point. The user could specify the relative spacing between arrowheads along the length of the edge. Another option would be to specify waypoints for the arrowheads.

This is obviously not a must have, but would be a feature that would give more flexibility to the user.

General idea: have an attribute (e.g., arrow_number) such that this number of arrowheads are added. We could leverage the interpolate function and apply it over several values. For example: if arrow_number = 3, then apply interpolate at 0.25, 0.50, and 0.75 (i.e., interpolate(p,t) for t in range(0,1,arrow_number+2)[2:end-1]).

Add ability to plot single node cycles

julia> g = SimpleDiGraph(4)
{4, 0} directed simple Int64 graph

julia> add_edge!(g, 1, 1)
true

julia> g
{4, 1} directed simple Int64 graph

julia> g
{4, 1} directed simple Int64 graph

julia> using GraphMakie

julia> using CairoMakie

julia> graphplot(g)
ERROR: MethodError: no method matching repeat(::Float64; inner=2)
Closest candidates are:
  repeat(::AbstractArray; inner, outer) at abstractarraymath.jl:260
  repeat(::AbstractArray, ::Any...) at abstractarraymath.jl:223 got unsupported keyword argument "inner"
  repeat(::Char, ::Integer) at strings/string.jl:334 got unsupported keyword argument "inner"

3D rotation doesn't move node labels

image

While plotting a 3D graph with node labels, it seems the labels won't rotate with the graph, instead staying fixed at their location. (This is under WGLMakie and Pluto with JSServe)

Exception while generating log record

┌ Error: Exception while generating log record in module GraphMakie at /home/fbanning/.julia/packages/GraphMakie/LdnRk/src/recipes.jl:408
│   exception =
│    UndefVarError: N not defined
│    Stacktrace:
│      [1] macro expansion
│        @ ./logging.jl:360 [inlined]
│      [2] find_edge_paths(g::StaticGraphs.StaticDiGraph{UInt16, UInt16}, attr::Attributes, pos::Vector{Point{2, Float32}})
│        @ GraphMakie ~/.julia/packages/GraphMakie/LdnRk/src/recipes.jl:408
│      [3] (::GraphMakie.var"#23#40"{Combined{GraphMakie.graphplot, Tuple{StaticGraphs.StaticDiGraph{UInt16, UInt16}}}, Observable{StaticGraphs.StaticDiGraph{UInt16, UInt16}}})(pos::Vector{Point{2, Float32}}, s::MakieCore.Automatic, d::MakieCore.Automatic, w::MakieCore.Automatic)
│        @ GraphMakie ~/.julia/packages/GraphMakie/LdnRk/src/recipes.jl:199
│      [4] lift(::Function, ::Observable{Any}, ::Observable{Any}, ::Vararg{Any}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
│        @ Makie ~/.julia/packages/Makie/lgPZh/src/interaction/observables.jl:30
│      [5] lift(::Function, ::Observable{Any}, ::Observable{Any}, ::Observable{Any}, ::Vararg{Any})
│        @ Makie ~/.julia/packages/Makie/lgPZh/src/interaction/observables.jl:27
│      [6] plot!(gp::Combined{GraphMakie.graphplot, Tuple{StaticGraphs.StaticDiGraph{UInt16, UInt16}}})
│        @ GraphMakie ~/.julia/packages/GraphMakie/LdnRk/src/recipes.jl:197
│      [7] plot!(scene::Combined{OSMMakie.osmplot, Tuple{LightOSM.OSMGraph{Int32, Int64, Float64}}}, P::Type{Combined{GraphMakie.graphplot, Tuple{StaticGraphs.StaticDiGraph{UInt16, UInt16}}}}, attributes::Attributes, input::Tuple{Observable{StaticGraphs.StaticDiGraph{UInt16, UInt16}}}, args::Observable{Tuple{StaticGraphs.StaticDiGraph{UInt16, UInt16}}})
│        @ Makie ~/.julia/packages/Makie/lgPZh/src/interfaces.jl:411
│      [8] plot!(scene::Combined{OSMMakie.osmplot, Tuple{LightOSM.OSMGraph{Int32, Int64, Float64}}}, P::Type{Combined{GraphMakie.graphplot}}, attributes::Attributes, args::StaticGraphs.StaticDiGraph{UInt16, UInt16}; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
│        @ Makie ~/.julia/packages/Makie/lgPZh/src/interfaces.jl:319
│      [9] plot!(scene::Combined{OSMMakie.osmplot, Tuple{LightOSM.OSMGraph{Int32, Int64, Float64}}}, P::Type{Combined{GraphMakie.graphplot}}, attributes::Attributes, args::StaticGraphs.StaticDiGraph{UInt16, UInt16})
│        @ Makie ~/.julia/packages/Makie/lgPZh/src/interfaces.jl:287
│     [10] #plot!#148
│        @ ~/.julia/packages/Makie/lgPZh/src/interfaces.jl:270 [inlined]
│     [11] graphplot!(::Combined{OSMMakie.osmplot, Tuple{LightOSM.OSMGraph{Int32, Int64, Float64}}}, ::Vararg{Any}; attributes::Base.Pairs{Symbol, Any, NTuple{10, Symbol}, NamedTuple{(:layout, :node_color, :node_size, :nlabels, :nlabels_textsize, :edge_color, :edge_width, :elabels, :elabels_textsize, :arrow_attr), Tuple{OSMMakie.var"#10#16"{Vector{Point2{Float64}}}, Vector{ColorTypes.RGB{FixedPointNumbers.N0f8}}, Vector{Int64}, Observable{Nothing}, Int64, Vector{ColorTypes.RGB{FixedPointNumbers.N0f8}}, Vector{Int64}, Observable{Nothing}, Int64, NamedTuple{(:markersize, :color), Tuple{Vector{Int64}, Symbol}}}}})
│        @ GraphMakie ~/.julia/packages/MakieCore/A0hGm/src/recipes.jl:37
│     [12] plot!(osmplot::Combined{OSMMakie.osmplot, Tuple{LightOSM.OSMGraph{Int32, Int64, Float64}}})
│        @ OSMMakie ~/.julia/packages/OSMMakie/dXQe5/src/recipe.jl:81
│     [13] plot!(scene::Combined{InteractiveDynamics._abmplot, Tuple{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}}}, P::Type{Combined{OSMMakie.osmplot, Tuple{LightOSM.OSMGraph{Int32, Int64, Float64}}}}, attributes::Attributes, input::Tuple{Observable{LightOSM.OSMGraph{Int32, Int64, Float64}}}, args::Observable{Tuple{LightOSM.OSMGraph{Int32, Int64, Float64}}})
│        @ Makie ~/.julia/packages/Makie/lgPZh/src/interfaces.jl:411
│     [14] plot!(scene::Combined{InteractiveDynamics._abmplot, Tuple{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}}}, P::Type{Combined{OSMMakie.osmplot}}, attributes::Attributes, args::LightOSM.OSMGraph{Int32, Int64, Float64}; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
│        @ Makie ~/.julia/packages/Makie/lgPZh/src/interfaces.jl:319
│     [15] plot!(scene::Combined{InteractiveDynamics._abmplot, Tuple{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}}}, P::Type{Combined{OSMMakie.osmplot}}, attributes::Attributes, args::LightOSM.OSMGraph{Int32, Int64, Float64})
│        @ Makie ~/.julia/packages/Makie/lgPZh/src/interfaces.jl:287
│     [16] plot!(P::Type{Combined{OSMMakie.osmplot}}, scene::Combined{InteractiveDynamics._abmplot, Tuple{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}}}, args::LightOSM.OSMGraph{Int32, Int64, Float64}; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
│        @ Makie ~/.julia/packages/Makie/lgPZh/src/interfaces.jl:270
│     [17] plot!(P::Type{Combined{OSMMakie.osmplot}}, scene::Combined{InteractiveDynamics._abmplot, Tuple{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}}}, args::LightOSM.OSMGraph{Int32, Int64, Float64})
│        @ Makie ~/.julia/packages/Makie/lgPZh/src/interfaces.jl:269
│     [18] osmplot!(::Combined{InteractiveDynamics._abmplot, Tuple{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}}}, ::Vararg{Any}; attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
│        @ OSMMakie ~/.julia/packages/MakieCore/A0hGm/src/recipes.jl:37
│     [19] osmplot!
│        @ ~/.julia/packages/MakieCore/A0hGm/src/recipes.jl:37 [inlined]
│     [20] plot!(abmplot::Combined{InteractiveDynamics._abmplot, Tuple{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}}})
│        @ InteractiveDynamics ~/.julia/dev/InteractiveDynamics/src/agents/abmplot.jl:218
│     [21] plot!(scene::Scene, P::Type{Combined{InteractiveDynamics._abmplot, Tuple{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}}}}, attributes::Attributes, input::Tuple{Observable{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}}}, args::Observable{Tuple{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}}})
│        @ Makie ~/.julia/packages/Makie/lgPZh/src/interfaces.jl:401
│     [22] plot!(scene::Scene, P::Type{Combined{InteractiveDynamics._abmplot}}, attributes::Attributes, args::AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
│        @ Makie ~/.julia/packages/Makie/lgPZh/src/interfaces.jl:319
│     [23] plot!(scene::Scene, P::Type{Combined{InteractiveDynamics._abmplot}}, attributes::Attributes, args::AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister})
│        @ Makie ~/.julia/packages/Makie/lgPZh/src/interfaces.jl:287
│     [24] plot!(la::Axis, P::Type{Combined{InteractiveDynamics._abmplot}}, attributes::Attributes, args::AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
│        @ Makie.MakieLayout ~/.julia/packages/Makie/lgPZh/src/makielayout/layoutables/axis.jl:693
│     [25] plot!
│        @ ~/.julia/packages/Makie/lgPZh/src/makielayout/layoutables/axis.jl:688 [inlined]
│     [26] #plot!#340
│        @ ~/.julia/packages/Makie/lgPZh/src/makielayout/layoutables/axis.jl:705 [inlined]
│     [27] _abmplot!(::Axis, ::Vararg{Any}; attributes::Base.Pairs{Symbol, Any, NTuple{6, Symbol}, NamedTuple{(:ax, :abmobs, :add_controls, :_add_interaction, :ac, :as), Tuple{Axis, ABMObservable{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}, typeof(Agents.Models.zombie_agent_step!), typeof(dummystep), Nothing, Nothing, Nothing, Nothing, Bool}, Bool, Bool, typeof(aczombie), typeof(aszombie)}}})
│        @ InteractiveDynamics ~/.julia/packages/MakieCore/A0hGm/src/recipes.jl:37
│     [28] abmplot!(ax::Axis, model::AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Agents.Models.Zombie, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, Random.MersenneTwister}; agent_step!::Function, model_step!::Function, adata::Nothing, mdata::Nothing, when::Bool, _add_interaction::Bool, add_controls::Bool, enable_inspection::Bool, kwargs::Base.Pairs{Symbol, Function, Tuple{Symbol, Symbol}, NamedTuple{(:ac, :as), Tuple{typeof(aczombie), typeof(aszombie)}}})
│        @ InteractiveDynamics ~/.julia/dev/InteractiveDynamics/src/agents/abmplot.jl:132
│     [29] top-level scope
│        @ ~/Code/ID-test-area/examples/agents/agents_osm.jl:16
│     [30] eval
│        @ ./boot.jl:373 [inlined]
│     [31] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
│        @ Base ./loading.jl:1196
│     [32] invokelatest(::Any, ::Any, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
│        @ Base ./essentials.jl:716
│     [33] invokelatest(::Any, ::Any, ::Vararg{Any})
│        @ Base ./essentials.jl:714
│     [34] inlineeval(m::Module, code::String, code_line::Int64, code_column::Int64, file::String; softscope::Bool)
│        @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.5/scripts/packages/VSCodeServer/src/eval.jl:211
│     [35] (::VSCodeServer.var"#60#64"{Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams})()
│        @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.5/scripts/packages/VSCodeServer/src/eval.jl:155
│     [36] withpath(f::VSCodeServer.var"#60#64"{Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams}, path::String)
│        @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.5/scripts/packages/VSCodeServer/src/repl.jl:184
│     [37] (::VSCodeServer.var"#59#63"{Bool, Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams})()
│        @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.5/scripts/packages/VSCodeServer/src/eval.jl:153
│     [38] hideprompt(f::VSCodeServer.var"#59#63"{Bool, Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams})
│        @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.5/scripts/packages/VSCodeServer/src/repl.jl:36
│     [39] (::VSCodeServer.var"#58#62"{Bool, Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams})()
│        @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.5/scripts/packages/VSCodeServer/src/eval.jl:124
│     [40] with_logstate(f::Function, logstate::Any)
│        @ Base.CoreLogging ./logging.jl:511
│     [41] with_logger
│        @ ./logging.jl:623 [inlined]
│     [42] (::VSCodeServer.var"#57#61"{VSCodeServer.ReplRunCodeRequestParams})()
│        @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.5/scripts/packages/VSCodeServer/src/eval.jl:201
│     [43] #invokelatest#2
│        @ ./essentials.jl:716 [inlined]
│     [44] invokelatest(::Any)
│        @ Base ./essentials.jl:714
│     [45] macro expansion
│        @ ~/.vscode/extensions/julialang.language-julia-1.6.5/scripts/packages/VSCodeServer/src/eval.jl:34 [inlined]
│     [46] (::VSCodeServer.var"#55#56")()
│        @ VSCodeServer ./task.jl:423
└ @ GraphMakie ~/.julia/packages/GraphMakie/LdnRk/src/recipes.jl:408

I've tried to run our Agents/InteractiveDynamics OSM example (relying on OSMMakie and thus on GraphMakie) with GraphMakie's master branch checked out but it threw this error. Can you make anything out of it?

Feat request: integrate `by_axis_local_stress_graph` network layout from GraphRecipes

I'm moving from Plot's GraphRecipies to GraphMakie.jl. GraphRecipies uses the Stress layout from NetworkLayout.jl as default. Here is an example of one of the graphs I'm trying to port.

plt = graphplot(g,
                nodeshape=nodeshapes,
                curves=false,
                nodecolor=nodecolors,
                nodeweights=nodeweights, # TODO: nodeweights are buggy in GraphRecipes
                nodesize=nodesize,
                size=plotsize,
                names=nodelabels,
                edgelabel=edgelabels,
                linecolor=:black,
                linealpha=0.5, 
              )

promedus-24-td_Screenshot_2021-09-13_17-50-21

and here is the same example ported to GraphMakie.jl also using the Stress layout from NetworkLayout.jl:

graphplot!(ax, g,
           layout = GraphMakie.NetworkLayout.Stress(seed=4),
           # layout = GraphMakie.NetworkLayout.Spring(C=1, seed=7),
           # layout = GraphMakie.NetworkLayout.Spectral(),
           nlabels = repr.(1:nv(g)),
           nlabels_align = (:center,:center),
           nlabels_color = :white,
           nlabels_textsize = 14 * scale,
           node_marker = :circle,
           node_size = 40 * scale,
           node_color=nodecolors,
          )

promedus-24-td-GraphMakie_Screenshot_2021-09-13_17-50-21

which, as you can see, is not as nicely laid out as with GraphRecipes. In theory, the layout should be the same since both packages rely on NetwrokLayout.jl. Would you know why this difference? I've played around with the parameters iterations, abstols, and reltols but the results are all very similar to the plot above.

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

Error when using `arrow_attr`

Description

GraphMakie throws an error when providing any attributes in the arrow_attr NamedTuple.

In the case of arrow_attr = (; color = :blue) we get:

ERROR: `Makie.convert_arguments` for the plot type Scatter{Tuple{Vector{Point{2, Float32}}, Pair{Symbol, Observable{Any}}}} and its conversion trait PointBased() was unsuccessful.

The signature that could not be converted was:
::Vector{Point{2, Float32}}, ::Pair{Symbol, Observable{Any}}

Makie needs to convert all plot input arguments to types that can be consumed by the backends (typically Arrays with Float32 elements).
You can define a method for `Makie.convert_arguments` (a type recipe) for these types or their supertypes to make this set of arguments convertible (See http://makie.juliaplots.org/stable/documentation/recipes/index.html).

Alternatively, you can define `Makie.convert_single_argument` for single arguments which have types that are unknown to Makie but which can be converted to known types and fed back to the conversion pipeline.

Stacktrace:
  [1] error(s::String)
    @ Base ./error.jl:33
  [2] convert_arguments(::Type{Scatter{Tuple{Vector{Point{2, Float32}}, Pair{Symbol, Observable{Any}}}}}, ::Vector{Point{2, Float32}}, ::Vararg{Any}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/conversions.jl:17
  [3] convert_arguments(::Type{Scatter{Tuple{Vector{Point{2, Float32}}, Pair{Symbol, Observable{Any}}}}}, ::Vector{Point{2, Float32}}, ::Pair{Symbol, Observable{Any}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/conversions.jl:8
  [4] plot!(::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}, ::Type{Scatter}, ::Attributes, ::Observable{Vector{Point{2, Float32}}}, ::Vararg{Any}; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:321
  [5] plot!(::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}, ::Type{Scatter}, ::Attributes, ::Observable{Vector{Point{2, Float32}}}, ::Pair{Symbol, Observable{Any}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:308
  [6] plot!(::Type{Scatter}, ::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}, ::Observable{Vector{Point{2, Float32}}}, ::Vararg{Any}; kw_attributes::Base.Pairs{Symbol, Any, NTuple{7, Symbol}, NamedTuple{(:marker, :markersize, :color, :rotations, :strokewidth, :markerspace, :visible), Tuple{Char, Observable{Any}, Observable{Any}, Observable{Billboard{Vector{Float32}}}, Float64, UnionAll, Observable{Bool}}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:291
  [7] scatter!(::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}, ::Vararg{Any}; attributes::Base.Pairs{Symbol, Any, NTuple{7, Symbol}, NamedTuple{(:marker, :markersize, :color, :rotations, :strokewidth, :markerspace, :visible), Tuple{Char, Observable{Any}, Observable{Any}, Observable{Billboard{Vector{Float32}}}, Float64, UnionAll, Observable{Bool}}}})
    @ MakieCore ~/.julia/packages/MakieCore/S8PkO/src/recipes.jl:35
  [8] plot!(gp::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}})
    @ GraphMakie ~/.julia/packages/GraphMakie/tEQ8U/src/recipes.jl:195
  [9] plot!(scene::Scene, P::Type{Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}}, attributes::Attributes, input::Tuple{Observable{SimpleDiGraph{Int64}}}, args::Observable{Tuple{SimpleDiGraph{Int64}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:428
 [10] plot!(scene::Scene, P::Type{Combined{GraphMakie.graphplot}}, attributes::Attributes, args::SimpleDiGraph{Int64}; kw_attributes::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:show_axis,), Tuple{Bool}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:339
 [11] plot(P::Type{Combined{GraphMakie.graphplot}}, args::SimpleDiGraph{Int64}; axis::NamedTuple{(), Tuple{}}, figure::NamedTuple{(), Tuple{}}, kw_attributes::Base.Pairs{Symbol, Any, NTuple{4, Symbol}, NamedTuple{(:layout, :edge_attr, :node_attr, :arrow_attr), Tuple{Shell{Float64}, NamedTuple{(:color,), Tuple{Symbol}}, NamedTuple{(:color,), Tuple{Symbol}}, NamedTuple{(:color,), Tuple{Symbol}}}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/figureplotting.jl:28
 [12] #graphplot#13
    @ ~/.julia/packages/MakieCore/S8PkO/src/recipes.jl:31 [inlined]
 [13] top-level scope
    @ REPL[18]:1

caused by: MethodError: no method matching convert_arguments(::Type{Scatter{Tuple{Vector{Point{2, Float32}}, Pair{Symbol, Observable{Any}}}}}, ::Vector{Point{2, Float32}}, ::Pair{Symbol, Observable{Any}})
Closest candidates are:
  convert_arguments(::Union{Type{Any}, Type{<:AbstractPlot}}, ::Any...; kw...) at ~/.julia/packages/Makie/gQOQF/src/conversions.jl:7
  convert_arguments(::Type{<:Combined{Makie.qqplot}}, ::Any...; kwargs...) at ~/.julia/packages/Makie/gQOQF/src/stats/distributions.jl:40
  convert_arguments(::Type{<:Combined{Makie.qqnorm}}, ::Any...; qqline, kwargs...) at ~/.julia/packages/Makie/gQOQF/src/stats/distributions.jl:37
  ...
Stacktrace:
  [1] convert_arguments_individually(::Type{Scatter{Tuple{Vector{Point{2, Float32}}, Pair{Symbol, Observable{Any}}}}}, ::Vector{Point{2, Float32}}, ::Vararg{Any})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/conversions.jl:47
  [2] convert_arguments(::Type{Scatter{Tuple{Vector{Point{2, Float32}}, Pair{Symbol, Observable{Any}}}}}, ::Vector{Point{2, Float32}}, ::Vararg{Any}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/conversions.jl:14
  [3] convert_arguments(::Type{Scatter{Tuple{Vector{Point{2, Float32}}, Pair{Symbol, Observable{Any}}}}}, ::Vector{Point{2, Float32}}, ::Pair{Symbol, Observable{Any}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/conversions.jl:8
  [4] plot!(::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}, ::Type{Scatter}, ::Attributes, ::Observable{Vector{Point{2, Float32}}}, ::Vararg{Any}; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:321
  [5] plot!(::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}, ::Type{Scatter}, ::Attributes, ::Observable{Vector{Point{2, Float32}}}, ::Pair{Symbol, Observable{Any}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:308
  [6] plot!(::Type{Scatter}, ::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}, ::Observable{Vector{Point{2, Float32}}}, ::Vararg{Any}; kw_attributes::Base.Pairs{Symbol, Any, NTuple{7, Symbol}, NamedTuple{(:marker, :markersize, :color, :rotations, :strokewidth, :markerspace, :visible), Tuple{Char, Observable{Any}, Observable{Any}, Observable{Billboard{Vector{Float32}}}, Float64, UnionAll, Observable{Bool}}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:291
  [7] scatter!(::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}, ::Vararg{Any}; attributes::Base.Pairs{Symbol, Any, NTuple{7, Symbol}, NamedTuple{(:marker, :markersize, :color, :rotations, :strokewidth, :markerspace, :visible), Tuple{Char, Observable{Any}, Observable{Any}, Observable{Billboard{Vector{Float32}}}, Float64, UnionAll, Observable{Bool}}}})
    @ MakieCore ~/.julia/packages/MakieCore/S8PkO/src/recipes.jl:35
  [8] plot!(gp::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}})
    @ GraphMakie ~/.julia/packages/GraphMakie/tEQ8U/src/recipes.jl:195
  [9] plot!(scene::Scene, P::Type{Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}}, attributes::Attributes, input::Tuple{Observable{SimpleDiGraph{Int64}}}, args::Observable{Tuple{SimpleDiGraph{Int64}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:428
 [10] plot!(scene::Scene, P::Type{Combined{GraphMakie.graphplot}}, attributes::Attributes, args::SimpleDiGraph{Int64}; kw_attributes::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:show_axis,), Tuple{Bool}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:339
 [11] plot(P::Type{Combined{GraphMakie.graphplot}}, args::SimpleDiGraph{Int64}; axis::NamedTuple{(), Tuple{}}, figure::NamedTuple{(), Tuple{}}, kw_attributes::Base.Pairs{Symbol, Any, NTuple{4, Symbol}, NamedTuple{(:layout, :edge_attr, :node_attr, :arrow_attr), Tuple{Shell{Float64}, NamedTuple{(:color,), Tuple{Symbol}}, NamedTuple{(:color,), Tuple{Symbol}}, NamedTuple{(:color,), Tuple{Symbol}}}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/figureplotting.jl:28
 [12] #graphplot#13
    @ ~/.julia/packages/MakieCore/S8PkO/src/recipes.jl:31 [inlined]
 [13] top-level scope
    @ REPL[18]:1

caused by: MethodError: no method matching convert_arguments(::PointBased, ::Vector{Point{2, Float32}}, ::Pair{Symbol, Observable{Any}})
Closest candidates are:
  convert_arguments(::Type{<:Combined{Makie.qqplot}}, ::Any...; kwargs...) at ~/.julia/packages/Makie/gQOQF/src/stats/distributions.jl:40
  convert_arguments(::Type{<:Combined{Makie.qqnorm}}, ::Any...; qqline, kwargs...) at ~/.julia/packages/Makie/gQOQF/src/stats/distributions.jl:37
  convert_arguments(::Type{<:Combined{Makie.rangebars}}, ::Any, ::Any) at ~/.julia/packages/Makie/gQOQF/src/basic_recipes/error_and_rangebars.jl:115
  ...
Stacktrace:
  [1] convert_arguments(::Type{Scatter{Tuple{Vector{Point{2, Float32}}, Pair{Symbol, Observable{Any}}}}}, ::Vector{Point{2, Float32}}, ::Vararg{Any}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/conversions.jl:10
  [2] convert_arguments(::Type{Scatter{Tuple{Vector{Point{2, Float32}}, Pair{Symbol, Observable{Any}}}}}, ::Vector{Point{2, Float32}}, ::Pair{Symbol, Observable{Any}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/conversions.jl:8
  [3] plot!(::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}, ::Type{Scatter}, ::Attributes, ::Observable{Vector{Point{2, Float32}}}, ::Vararg{Any}; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:321
  [4] plot!(::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}, ::Type{Scatter}, ::Attributes, ::Observable{Vector{Point{2, Float32}}}, ::Pair{Symbol, Observable{Any}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:308
  [5] plot!(::Type{Scatter}, ::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}, ::Observable{Vector{Point{2, Float32}}}, ::Vararg{Any}; kw_attributes::Base.Pairs{Symbol, Any, NTuple{7, Symbol}, NamedTuple{(:marker, :markersize, :color, :rotations, :strokewidth, :markerspace, :visible), Tuple{Char, Observable{Any}, Observable{Any}, Observable{Billboard{Vector{Float32}}}, Float64, UnionAll, Observable{Bool}}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:291
  [6] scatter!(::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}, ::Vararg{Any}; attributes::Base.Pairs{Symbol, Any, NTuple{7, Symbol}, NamedTuple{(:marker, :markersize, :color, :rotations, :strokewidth, :markerspace, :visible), Tuple{Char, Observable{Any}, Observable{Any}, Observable{Billboard{Vector{Float32}}}, Float64, UnionAll, Observable{Bool}}}})
    @ MakieCore ~/.julia/packages/MakieCore/S8PkO/src/recipes.jl:35
  [7] plot!(gp::Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}})
    @ GraphMakie ~/.julia/packages/GraphMakie/tEQ8U/src/recipes.jl:195
  [8] plot!(scene::Scene, P::Type{Combined{GraphMakie.graphplot, Tuple{SimpleDiGraph{Int64}}}}, attributes::Attributes, input::Tuple{Observable{SimpleDiGraph{Int64}}}, args::Observable{Tuple{SimpleDiGraph{Int64}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:428
  [9] plot!(scene::Scene, P::Type{Combined{GraphMakie.graphplot}}, attributes::Attributes, args::SimpleDiGraph{Int64}; kw_attributes::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:show_axis,), Tuple{Bool}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/interfaces.jl:339
 [10] plot(P::Type{Combined{GraphMakie.graphplot}}, args::SimpleDiGraph{Int64}; axis::NamedTuple{(), Tuple{}}, figure::NamedTuple{(), Tuple{}}, kw_attributes::Base.Pairs{Symbol, Any, NTuple{4, Symbol}, NamedTuple{(:layout, :edge_attr, :node_attr, :arrow_attr), Tuple{Shell{Float64}, NamedTuple{(:color,), Tuple{Symbol}}, NamedTuple{(:color,), Tuple{Symbol}}, NamedTuple{(:color,), Tuple{Symbol}}}}})
    @ Makie ~/.julia/packages/Makie/gQOQF/src/figureplotting.jl:28
 [11] #graphplot#13
    @ ~/.julia/packages/MakieCore/S8PkO/src/recipes.jl:31 [inlined]
 [12] top-level scope
    @ REPL[18]:1

MWE

This still works with edge_attr and node_attr:

julia> g = SimpleDiGraph(5,20)
{5, 20} directed simple Int64 graph

julia> graphplot(g; layout = Shell(), edge_attr = (; color = :red), node_attr = (; color = :blue))

Screenshot_20220119_150423

But not when adding arrow_attr to simply also color the directed graph arrows.

julia> graphplot(g; layout = Shell(), edge_attr = (; color = :red), node_attr = (; color = :blue), arrow_attr = (; color = :blue))

Avoid node clipping with CairoMakie.jl as backend

Hi. I'm trying to generate a figure for a paper using GraphMakie.jl and CairoMakie.jl. I'm stuck with a small issue since I'm not very familiar with Makie.jl yet: In the image below, how can I avoid the clipping of the nodes in the corners?

06-grid3x3

I noticed that this is easy to fix using GLMakie using the mouse wheel to control the zoom:

image

However, I haven't been able to emulate this programatically to make it work with CairoMakie.jl.

Are nlabels_distance and nlabels_align working properly?

Hi! I have understood that nlabels_distance moves the labels in the direction determined by nlabels_align. However, increasing nlabels_distance is moving the node labels up when align is (:center, :bottom). How come? Is there a bug or is it something I did not understand about how nlabels_align determines the direction? I was expected the labels to move down when the vertical direction is :bottom. Cheers,

Exemple:

image

### A Pluto.jl notebook ###
# v0.18.1

using Markdown
using InteractiveUtils

# ╔═╡ 560feed0-98bd-11ec-1e02-cd284b028586
begin
	using Graphs
	using GLMakie, GraphMakie
end

# ╔═╡ 81730fe7-49e0-4d4b-8155-d41fd3849fc5
graph = smallgraph(:karate)

# ╔═╡ 3b3218d8-917e-4668-8044-16eb03ef77c4
graphplot(graph)

# ╔═╡ ed6351cb-9382-437a-abb0-bd10782a07e8
begin
	node_colors = fill(:white, nv(graph))
	node_colors[1] = :lightgray
	node_colors[34] = :lightgray
end

# ╔═╡ faf06569-a7d6-436e-a522-575758eab31c
begin
	node_labels = fill("", nv(graph))
	node_labels[1] = "Mr. Hi"
	node_labels[34] = "John A"
end

# ╔═╡ a76433a2-d967-4be7-8ca8-8f5a24ab6cc5
begin
	figure, axis, plt = graphplot(graph,
		node_color = node_colors,
		node_size = 14,
		node_attr = (strokewidth = 2, strokecolor = :lightgray),
		edge_color = :lightgray,
		edge_width = 2,
		nlabels = node_labels,
		nlabels_align = (:center, :bottom),
		nlabels_distance = 10)
	
	#hidespines!(axis)
	#hidedecorations!(axis)
	
	figure
end

# ╔═╡ e53a587b-9b65-4976-a708-e2c00361460c


# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
GraphMakie = "1ecd5474-83a3-4783-bb4f-06765db800d2"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"

[compat]
GLMakie = "~0.5.4"
GraphMakie = "~0.3.3"
Graphs = "~1.6.0"
"""

# ╔═╡ 00000000-0000-0000-0000-000000000002
PLUTO_MANIFEST_TOML_CONTENTS = """
# This file is machine-generated - editing it directly is not advised

[[AbstractFFTs]]
deps = ["ChainRulesCore", "LinearAlgebra"]
git-tree-sha1 = "6f1d9bc1c08f9f4a8fa92e3ea3cb50153a1b40d4"
uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c"
version = "1.1.0"

[[AbstractTrees]]
git-tree-sha1 = "03e0550477d86222521d254b741d470ba17ea0b5"
uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
version = "0.3.4"

[[Adapt]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "af92965fb30777147966f58acb05da51c5616b5f"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "3.3.3"

[[Animations]]
deps = ["Colors"]
git-tree-sha1 = "e81c509d2c8e49592413bfb0bb3b08150056c79d"
uuid = "27a7e980-b3e6-11e9-2bcd-0b925532e340"
version = "0.4.1"

[[ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"

[[ArnoldiMethod]]
deps = ["LinearAlgebra", "Random", "StaticArrays"]
git-tree-sha1 = "62e51b39331de8911e4a7ff6f5aaf38a5f4cc0ae"
uuid = "ec485272-7323-5ecc-a04f-4719b315124d"
version = "0.2.0"

[[ArrayInterface]]
deps = ["Compat", "IfElse", "LinearAlgebra", "Requires", "SparseArrays", "Static"]
git-tree-sha1 = "745233d77146ad221629590b6d82fe7f1ddb478f"
uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
version = "4.0.3"

[[Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"

[[Automa]]
deps = ["Printf", "ScanByte", "TranscodingStreams"]
git-tree-sha1 = "d50976f217489ce799e366d9561d56a98a30d7fe"
uuid = "67c07d97-cdcb-5c2c-af73-a7f9c32a568b"
version = "0.8.2"

[[AxisAlgorithms]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "WoodburyMatrices"]
git-tree-sha1 = "66771c8d21c8ff5e3a93379480a2307ac36863f7"
uuid = "13072b0f-2c55-5437-9ae7-d433b7a33950"
version = "1.0.1"

[[Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[Bzip2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "19a35467a82e236ff51bc17a3a44b69ef35185a2"
uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
version = "1.0.8+0"

[[CEnum]]
git-tree-sha1 = "215a9aa4a1f23fbd05b92769fdd62559488d70e9"
uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82"
version = "0.4.1"

[[Cairo_jll]]
deps = ["Artifacts", "Bzip2_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "4b859a208b2397a7a623a03449e4636bdb17bcf2"
uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a"
version = "1.16.1+1"

[[Calculus]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad"
uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9"
version = "0.5.1"

[[ChainRulesCore]]
deps = ["Compat", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "c9a6160317d1abe9c44b3beb367fd448117679ca"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.13.0"

[[ChangesOfVariables]]
deps = ["ChainRulesCore", "LinearAlgebra", "Test"]
git-tree-sha1 = "bf98fa45a0a4cee295de98d4c1462be26345b9a1"
uuid = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
version = "0.1.2"

[[ColorBrewer]]
deps = ["Colors", "JSON", "Test"]
git-tree-sha1 = "61c5334f33d91e570e1d0c3eb5465835242582c4"
uuid = "a2cac450-b92f-5266-8821-25eda20663c8"
version = "0.4.0"

[[ColorSchemes]]
deps = ["ColorTypes", "Colors", "FixedPointNumbers", "Random"]
git-tree-sha1 = "12fc73e5e0af68ad3137b886e3f7c1eacfca2640"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.17.1"

[[ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
git-tree-sha1 = "024fe24d83e4a5bf5fc80501a314ce0d1aa35597"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.11.0"

[[ColorVectorSpace]]
deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "SpecialFunctions", "Statistics", "TensorCore"]
git-tree-sha1 = "3f1f500312161f1ae067abe07d13b40f78f32e07"
uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4"
version = "0.9.8"

[[Colors]]
deps = ["ColorTypes", "FixedPointNumbers", "Reexport"]
git-tree-sha1 = "417b0ed7b8b838aa6ca0a87aadf1bb9eb111ce40"
uuid = "5ae59095-9a9b-59fe-a467-6f913c188581"
version = "0.12.8"

[[Compat]]
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
git-tree-sha1 = "44c37b4636bc54afac5c574d2d02b625349d6582"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.41.0"

[[CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"

[[Contour]]
deps = ["StaticArrays"]
git-tree-sha1 = "9f02045d934dc030edad45944ea80dbd1f0ebea7"
uuid = "d38c429a-6771-53c6-b99e-75d170b6e991"
version = "0.5.7"

[[DataAPI]]
git-tree-sha1 = "cc70b17275652eb47bc9e5f81635981f13cea5c8"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.9.0"

[[DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "3daef5523dd2e769dad2365274f760ff5f282c7d"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.11"

[[DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"

[[Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[DelimitedFiles]]
deps = ["Mmap"]
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"

[[DensityInterface]]
deps = ["InverseFunctions", "Test"]
git-tree-sha1 = "80c3e8639e3353e5d2912fb3a1916b8455e2494b"
uuid = "b429d917-457f-4dbc-8f4c-0cc954292b1d"
version = "0.4.0"

[[Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[Distributions]]
deps = ["ChainRulesCore", "DensityInterface", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsBase", "StatsFuns", "Test"]
git-tree-sha1 = "9d3c0c762d4666db9187f363a76b47f7346e673b"
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
version = "0.25.49"

[[DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "b19534d1895d702889b219c382a6e18010797f0b"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.8.6"

[[Downloads]]
deps = ["ArgTools", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"

[[DualNumbers]]
deps = ["Calculus", "NaNMath", "SpecialFunctions"]
git-tree-sha1 = "84f04fe68a3176a583b864e492578b9466d87f1e"
uuid = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74"
version = "0.6.6"

[[EarCut_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "3f3a2501fa7236e9b911e0f7a588c657e822bb6d"
uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5"
version = "2.2.3+0"

[[EllipsisNotation]]
deps = ["ArrayInterface"]
git-tree-sha1 = "d7ab55febfd0907b285fbf8dc0c73c0825d9d6aa"
uuid = "da5c29d0-fa7d-589e-88eb-ea29b0a81949"
version = "1.3.0"

[[Expat_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "ae13fcbc7ab8f16b0856729b050ef0c446aa3492"
uuid = "2e619515-83b5-522b-bb60-26c02a35a201"
version = "2.4.4+0"

[[FFMPEG]]
deps = ["FFMPEG_jll"]
git-tree-sha1 = "b57e3acbe22f8484b4b5ff66a7499717fe1a9cc8"
uuid = "c87230d0-a227-11e9-1b43-d7ebe4e7570a"
version = "0.4.1"

[[FFMPEG_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "Pkg", "Zlib_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"]
git-tree-sha1 = "d8a578692e3077ac998b50c0217dfd67f21d1e5f"
uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5"
version = "4.4.0+0"

[[FFTW]]
deps = ["AbstractFFTs", "FFTW_jll", "LinearAlgebra", "MKL_jll", "Preferences", "Reexport"]
git-tree-sha1 = "463cb335fa22c4ebacfd1faba5fde14edb80d96c"
uuid = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
version = "1.4.5"

[[FFTW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c6033cc3892d0ef5bb9cd29b7f2f0331ea5184ea"
uuid = "f5851436-0d7a-5f13-b9de-f02708fd171a"
version = "3.3.10+0"

[[FileIO]]
deps = ["Pkg", "Requires", "UUIDs"]
git-tree-sha1 = "80ced645013a5dbdc52cf70329399c35ce007fae"
uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
version = "1.13.0"

[[FillArrays]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "Statistics"]
git-tree-sha1 = "4c7d3757f3ecbcb9055870351078552b7d1dbd2d"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "0.13.0"

[[FixedPointNumbers]]
deps = ["Statistics"]
git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc"
uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
version = "0.8.4"

[[Fontconfig_jll]]
deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "21efd19106a55620a188615da6d3d06cd7f6ee03"
uuid = "a3f928ae-7b40-5064-980b-68af3947d34b"
version = "2.13.93+0"

[[Formatting]]
deps = ["Printf"]
git-tree-sha1 = "8339d61043228fdd3eb658d86c926cb282ae72a8"
uuid = "59287772-0a20-5a39-b81b-1366585eb4c0"
version = "0.4.2"

[[FreeType]]
deps = ["CEnum", "FreeType2_jll"]
git-tree-sha1 = "cabd77ab6a6fdff49bfd24af2ebe76e6e018a2b4"
uuid = "b38be410-82b0-50bf-ab77-7b57e271db43"
version = "4.0.0"

[[FreeType2_jll]]
deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "87eb71354d8ec1a96d4a7636bd57a7347dde3ef9"
uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7"
version = "2.10.4+0"

[[FreeTypeAbstraction]]
deps = ["ColorVectorSpace", "Colors", "FreeType", "GeometryBasics", "StaticArrays"]
git-tree-sha1 = "770050893e7bc8a34915b4b9298604a3236de834"
uuid = "663a7486-cb36-511b-a19d-713bb74d65c9"
version = "0.9.5"

[[FriBidi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "aa31987c2ba8704e23c6c8ba8a4f769d5d7e4f91"
uuid = "559328eb-81f9-559d-9380-de523a88c83c"
version = "1.0.10+0"

[[GLFW]]
deps = ["GLFW_jll"]
git-tree-sha1 = "35dbc482f0967d8dceaa7ce007d16f9064072166"
uuid = "f7f18e0c-5ee9-5ccd-a5bf-e8befd85ed98"
version = "3.4.1"

[[GLFW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"]
git-tree-sha1 = "51d2dfe8e590fbd74e7a842cf6d13d8a2f45dc01"
uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89"
version = "3.3.6+0"

[[GLMakie]]
deps = ["ColorTypes", "Colors", "FileIO", "FixedPointNumbers", "FreeTypeAbstraction", "GLFW", "GeometryBasics", "LinearAlgebra", "Makie", "Markdown", "MeshIO", "ModernGL", "Observables", "Printf", "Serialization", "ShaderAbstractions", "StaticArrays"]
git-tree-sha1 = "b8140fd8718490698ce878480ff6db751d336f75"
uuid = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
version = "0.5.4"

[[GeometryBasics]]
deps = ["EarCut_jll", "IterTools", "LinearAlgebra", "StaticArrays", "StructArrays", "Tables"]
git-tree-sha1 = "58bcdf5ebc057b085e58d95c138725628dd7453c"
uuid = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
version = "0.4.1"

[[Gettext_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "9b02998aba7bf074d14de89f9d37ca24a1a0b046"
uuid = "78b55507-aeef-58d4-861c-77aaff3498b1"
version = "0.21.0+0"

[[Glib_jll]]
deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "a32d672ac2c967f3deb8a81d828afc739c838a06"
uuid = "7746bdde-850d-59dc-9ae8-88ece973131d"
version = "2.68.3+2"

[[GraphMakie]]
deps = ["GeometryBasics", "Graphs", "LinearAlgebra", "Makie", "NetworkLayout", "StaticArrays"]
git-tree-sha1 = "1cbb534e0e0e8b529239500f52820e5a57016d0d"
uuid = "1ecd5474-83a3-4783-bb4f-06765db800d2"
version = "0.3.3"

[[Graphics]]
deps = ["Colors", "LinearAlgebra", "NaNMath"]
git-tree-sha1 = "1c5a84319923bea76fa145d49e93aa4394c73fc2"
uuid = "a2bd30eb-e257-5431-a919-1863eab51364"
version = "1.1.1"

[[Graphite2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "344bf40dcab1073aca04aa0df4fb092f920e4011"
uuid = "3b182d85-2403-5c21-9c21-1e1f0cc25472"
version = "1.3.14+0"

[[Graphs]]
deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"]
git-tree-sha1 = "57c021de207e234108a6f1454003120a1bf350c4"
uuid = "86223c79-3864-5bf0-83f7-82e725a168b6"
version = "1.6.0"

[[GridLayoutBase]]
deps = ["GeometryBasics", "InteractiveUtils", "Observables"]
git-tree-sha1 = "169c3dc5acae08835a573a8a3e25c62f689f8b5c"
uuid = "3955a311-db13-416c-9275-1d80ed98e5e9"
version = "0.6.5"

[[Grisu]]
git-tree-sha1 = "53bb909d1151e57e2484c3d1b53e19552b887fb2"
uuid = "42e2da0e-8278-4e71-bc24-59509adca0fe"
version = "1.0.2"

[[HarfBuzz_jll]]
deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "Graphite2_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg"]
git-tree-sha1 = "129acf094d168394e80ee1dc4bc06ec835e510a3"
uuid = "2e76f6c2-a576-52d4-95c1-20adfe4de566"
version = "2.8.1+1"

[[HypergeometricFunctions]]
deps = ["DualNumbers", "LinearAlgebra", "SpecialFunctions", "Test"]
git-tree-sha1 = "65e4589030ef3c44d3b90bdc5aac462b4bb05567"
uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
version = "0.3.8"

[[IfElse]]
git-tree-sha1 = "debdd00ffef04665ccbb3e150747a77560e8fad1"
uuid = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
version = "0.1.1"

[[ImageCore]]
deps = ["AbstractFFTs", "ColorVectorSpace", "Colors", "FixedPointNumbers", "Graphics", "MappedArrays", "MosaicViews", "OffsetArrays", "PaddedViews", "Reexport"]
git-tree-sha1 = "9a5c62f231e5bba35695a20988fc7cd6de7eeb5a"
uuid = "a09fc81d-aa75-5fe9-8630-4744c3626534"
version = "0.9.3"

[[ImageIO]]
deps = ["FileIO", "JpegTurbo", "Netpbm", "OpenEXR", "PNGFiles", "QOI", "Sixel", "TiffImages", "UUIDs"]
git-tree-sha1 = "464bdef044df52e6436f8c018bea2d48c40bb27b"
uuid = "82e4d734-157c-48bb-816b-45c225c6df19"
version = "0.6.1"

[[Imath_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "87f7662e03a649cffa2e05bf19c303e168732d3e"
uuid = "905a6f67-0a94-5f89-b386-d35d92009cd1"
version = "3.1.2+0"

[[IndirectArrays]]
git-tree-sha1 = "012e604e1c7458645cb8b436f8fba789a51b257f"
uuid = "9b13fd28-a010-5f03-acff-a1bbcff69959"
version = "1.0.0"

[[Inflate]]
git-tree-sha1 = "f5fc07d4e706b84f72d54eedcc1c13d92fb0871c"
uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
version = "0.1.2"

[[IntelOpenMP_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "d979e54b71da82f3a65b62553da4fc3d18c9004c"
uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0"
version = "2018.0.3+2"

[[InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[Interpolations]]
deps = ["AxisAlgorithms", "ChainRulesCore", "LinearAlgebra", "OffsetArrays", "Random", "Ratios", "Requires", "SharedArrays", "SparseArrays", "StaticArrays", "WoodburyMatrices"]
git-tree-sha1 = "b15fc0a95c564ca2e0a7ae12c1f095ca848ceb31"
uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
version = "0.13.5"

[[IntervalSets]]
deps = ["Dates", "EllipsisNotation", "Statistics"]
git-tree-sha1 = "3cc368af3f110a767ac786560045dceddfc16758"
uuid = "8197267c-284f-5f27-9208-e0e47529a953"
version = "0.5.3"

[[InverseFunctions]]
deps = ["Test"]
git-tree-sha1 = "a7254c0acd8e62f1ac75ad24d5db43f5f19f3c65"
uuid = "3587e190-3f89-42d0-90ee-14403ec27112"
version = "0.1.2"

[[IrrationalConstants]]
git-tree-sha1 = "7fd44fd4ff43fc60815f8e764c0f352b83c49151"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.1.1"

[[Isoband]]
deps = ["isoband_jll"]
git-tree-sha1 = "f9b6d97355599074dc867318950adaa6f9946137"
uuid = "f1662d9f-8043-43de-a69a-05efc1cc6ff4"
version = "0.1.1"

[[IterTools]]
git-tree-sha1 = "fa6287a4469f5e048d763df38279ee729fbd44e5"
uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
version = "1.4.0"

[[IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"

[[JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "abc9885a7ca2052a736a600f7fa66209f96506e1"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.4.1"

[[JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "3c837543ddb02250ef42f4738347454f95079d4e"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.3"

[[JpegTurbo]]
deps = ["CEnum", "FileIO", "ImageCore", "JpegTurbo_jll", "TOML"]
git-tree-sha1 = "a77b273f1ddec645d1b7c4fd5fb98c8f90ad10a5"
uuid = "b835a17e-a41a-41e7-81f0-2f016b05efe0"
version = "0.1.1"

[[JpegTurbo_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b53380851c6e6664204efb2e62cd24fa5c47e4ba"
uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8"
version = "2.1.2+0"

[[KernelDensity]]
deps = ["Distributions", "DocStringExtensions", "FFTW", "Interpolations", "StatsBase"]
git-tree-sha1 = "591e8dc09ad18386189610acafb970032c519707"
uuid = "5ab0869b-81aa-558d-bb23-cbf5423bbe9b"
version = "0.6.3"

[[LAME_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "f6250b16881adf048549549fba48b1161acdac8c"
uuid = "c1c5ebd0-6772-5130-a774-d5fcae4a789d"
version = "3.100.1+0"

[[LZO_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "e5b909bcf985c5e2605737d2ce278ed791b89be6"
uuid = "dd4b983a-f0e5-5f8d-a1b7-129d4a5fb1ac"
version = "2.10.1+0"

[[LaTeXStrings]]
git-tree-sha1 = "f2355693d6778a178ade15952b7ac47a4ff97996"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.3.0"

[[LazyArtifacts]]
deps = ["Artifacts", "Pkg"]
uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3"

[[LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"

[[LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"

[[LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"

[[Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[Libffi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "0b4a5d71f3e5200a7dff793393e09dfc2d874290"
uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490"
version = "3.2.2+1"

[[Libgcrypt_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgpg_error_jll", "Pkg"]
git-tree-sha1 = "64613c82a59c120435c067c2b809fc61cf5166ae"
uuid = "d4300ac3-e22c-5743-9152-c294e39db1e4"
version = "1.8.7+0"

[[Libglvnd_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll", "Xorg_libXext_jll"]
git-tree-sha1 = "7739f837d6447403596a75d19ed01fd08d6f56bf"
uuid = "7e76a0d4-f3c7-5321-8279-8d96eeed0f29"
version = "1.3.0+3"

[[Libgpg_error_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c333716e46366857753e273ce6a69ee0945a6db9"
uuid = "7add5ba3-2f88-524e-9cd5-f83b8a55f7b8"
version = "1.42.0+0"

[[Libiconv_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "42b62845d70a619f063a7da093d995ec8e15e778"
uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531"
version = "1.16.1+1"

[[Libmount_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "9c30530bf0effd46e15e0fdcf2b8636e78cbbd73"
uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9"
version = "2.35.0+0"

[[Libuuid_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7f3efec06033682db852f8b3bc3c1d2b0a0ab066"
uuid = "38a345b3-de98-5d2b-a5d3-14cd9215e700"
version = "2.36.0+0"

[[LinearAlgebra]]
deps = ["Libdl"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[LogExpFunctions]]
deps = ["ChainRulesCore", "ChangesOfVariables", "DocStringExtensions", "InverseFunctions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "e5718a00af0ab9756305a0392832c8952c7426c1"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.6"

[[Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[MKL_jll]]
deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"]
git-tree-sha1 = "5455aef09b40e5020e1520f551fa3135040d4ed0"
uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7"
version = "2021.1.1+2"

[[MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "3d3e902b31198a27340d0bf00d6ac452866021cf"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.9"

[[Makie]]
deps = ["Animations", "Base64", "ColorBrewer", "ColorSchemes", "ColorTypes", "Colors", "Contour", "Distributions", "DocStringExtensions", "FFMPEG", "FileIO", "FixedPointNumbers", "Formatting", "FreeType", "FreeTypeAbstraction", "GeometryBasics", "GridLayoutBase", "ImageIO", "IntervalSets", "Isoband", "KernelDensity", "LaTeXStrings", "LinearAlgebra", "MakieCore", "Markdown", "Match", "MathTeXEngine", "Observables", "OffsetArrays", "Packing", "PlotUtils", "PolygonOps", "Printf", "Random", "RelocatableFolders", "Serialization", "Showoff", "SignedDistanceFields", "SparseArrays", "StaticArrays", "Statistics", "StatsBase", "StatsFuns", "StructArrays", "UnicodeFun"]
git-tree-sha1 = "cd0fd02ab0d129f03515b7b68ca77fb670ef2e61"
uuid = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
version = "0.16.5"

[[MakieCore]]
deps = ["Observables"]
git-tree-sha1 = "c5fb1bfac781db766f9e4aef96adc19a729bc9b2"
uuid = "20f20a25-4f0e-4fdf-b5d1-57303727442b"
version = "0.2.1"

[[MappedArrays]]
git-tree-sha1 = "e8b359ef06ec72e8c030463fe02efe5527ee5142"
uuid = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900"
version = "0.4.1"

[[Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[Match]]
git-tree-sha1 = "1d9bc5c1a6e7ee24effb93f175c9342f9154d97f"
uuid = "7eb4fadd-790c-5f42-8a69-bfa0b872bfbf"
version = "1.2.0"

[[MathTeXEngine]]
deps = ["AbstractTrees", "Automa", "DataStructures", "FreeTypeAbstraction", "GeometryBasics", "LaTeXStrings", "REPL", "RelocatableFolders", "Test"]
git-tree-sha1 = "70e733037bbf02d691e78f95171a1fa08cdc6332"
uuid = "0a4f8689-d25c-4efe-a92b-7142dfc1aa53"
version = "0.2.1"

[[MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"

[[MeshIO]]
deps = ["ColorTypes", "FileIO", "GeometryBasics", "Printf"]
git-tree-sha1 = "8be09d84a2d597c7c0c34d7d604c039c9763e48c"
uuid = "7269a6da-0436-5bbc-96c2-40638cbb6118"
version = "0.4.10"

[[Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "bf210ce90b6c9eed32d25dbcae1ebc565df2687f"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "1.0.2"

[[Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[ModernGL]]
deps = ["Libdl"]
git-tree-sha1 = "344f8896e55541e30d5ccffcbf747c98ad57ca47"
uuid = "66fc600b-dfda-50eb-8b99-91cfa97b1301"
version = "1.1.4"

[[MosaicViews]]
deps = ["MappedArrays", "OffsetArrays", "PaddedViews", "StackViews"]
git-tree-sha1 = "b34e3bc3ca7c94914418637cb10cc4d1d80d877d"
uuid = "e94cdb99-869f-56ef-bcf0-1ae2bcbe0389"
version = "0.3.3"

[[MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"

[[NaNMath]]
git-tree-sha1 = "b086b7ea07f8e38cf122f5016af580881ac914fe"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "0.3.7"

[[Netpbm]]
deps = ["FileIO", "ImageCore"]
git-tree-sha1 = "18efc06f6ec36a8b801b23f076e3c6ac7c3bf153"
uuid = "f09324ee-3d7c-5217-9330-fc30815ba969"
version = "1.0.2"

[[NetworkLayout]]
deps = ["GeometryBasics", "LinearAlgebra", "Random", "Requires", "SparseArrays"]
git-tree-sha1 = "cac8fc7ba64b699c678094fa630f49b80618f625"
uuid = "46757867-2c16-5918-afeb-47bfcb05e46a"
version = "0.4.4"

[[NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"

[[Observables]]
git-tree-sha1 = "fe29afdef3d0c4a8286128d4e45cc50621b1e43d"
uuid = "510215fc-4207-5dde-b226-833fc4488ee2"
version = "0.4.0"

[[OffsetArrays]]
deps = ["Adapt"]
git-tree-sha1 = "043017e0bdeff61cfbb7afeb558ab29536bbb5ed"
uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
version = "1.10.8"

[[Ogg_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "887579a3eb005446d514ab7aeac5d1d027658b8f"
uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051"
version = "1.3.5+1"

[[OpenEXR]]
deps = ["Colors", "FileIO", "OpenEXR_jll"]
git-tree-sha1 = "327f53360fdb54df7ecd01e96ef1983536d1e633"
uuid = "52e1d378-f018-4a11-a4be-720524705ac7"
version = "0.3.2"

[[OpenEXR_jll]]
deps = ["Artifacts", "Imath_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "923319661e9a22712f24596ce81c54fc0366f304"
uuid = "18a262bb-aa17-5467-a713-aee519bc75cb"
version = "3.1.1+0"

[[OpenLibm_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"

[[OpenSSL_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "648107615c15d4e09f7eca16307bc821c1f718d8"
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
version = "1.1.13+0"

[[OpenSpecFun_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
version = "0.5.5+0"

[[Opus_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "51a08fb14ec28da2ec7a927c4337e4332c2a4720"
uuid = "91d4177d-7536-5919-b921-800302f37372"
version = "1.3.2+0"

[[OrderedCollections]]
git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.4.1"

[[PCRE_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b2a7af664e098055a7529ad1a900ded962bca488"
uuid = "2f80f16e-611a-54ab-bc61-aa92de5b98fc"
version = "8.44.0+0"

[[PDMats]]
deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"]
git-tree-sha1 = "7e2166042d1698b6072352c74cfd1fca2a968253"
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
version = "0.11.6"

[[PNGFiles]]
deps = ["Base64", "CEnum", "ImageCore", "IndirectArrays", "OffsetArrays", "libpng_jll"]
git-tree-sha1 = "eb4dbb8139f6125471aa3da98fb70f02dc58e49c"
uuid = "f57f5aa1-a3ce-4bc8-8ab9-96f992907883"
version = "0.3.14"

[[Packing]]
deps = ["GeometryBasics"]
git-tree-sha1 = "1155f6f937fa2b94104162f01fa400e192e4272f"
uuid = "19eb6ba3-879d-56ad-ad62-d5c202156566"
version = "0.4.2"

[[PaddedViews]]
deps = ["OffsetArrays"]
git-tree-sha1 = "03a7a85b76381a3d04c7a1656039197e70eda03d"
uuid = "5432bcbf-9aad-5242-b902-cca2824c8663"
version = "0.5.11"

[[Parsers]]
deps = ["Dates"]
git-tree-sha1 = "13468f237353112a01b2d6b32f3d0f80219944aa"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.2.2"

[[Pixman_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b4f5d02549a10e20780a24fce72bea96b6329e29"
uuid = "30392449-352a-5448-841d-b1acce4e97dc"
version = "0.40.1+0"

[[Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[[PkgVersion]]
deps = ["Pkg"]
git-tree-sha1 = "a7a7e1a88853564e551e4eba8650f8c38df79b37"
uuid = "eebad327-c553-4316-9ea0-9fa01ccd7688"
version = "0.1.1"

[[PlotUtils]]
deps = ["ColorSchemes", "Colors", "Dates", "Printf", "Random", "Reexport", "Statistics"]
git-tree-sha1 = "6f1b25e8ea06279b5689263cc538f51331d7ca17"
uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043"
version = "1.1.3"

[[PolygonOps]]
git-tree-sha1 = "77b3d3605fc1cd0b42d95eba87dfcd2bf67d5ff6"
uuid = "647866c9-e3ac-4575-94e7-e3d426903924"
version = "0.1.2"

[[Preferences]]
deps = ["TOML"]
git-tree-sha1 = "de893592a221142f3db370f48290e3a2ef39998f"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.2.4"

[[Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[ProgressMeter]]
deps = ["Distributed", "Printf"]
git-tree-sha1 = "afadeba63d90ff223a6a48d2009434ecee2ec9e8"
uuid = "92933f4c-e287-5a05-a399-4b506db050ca"
version = "1.7.1"

[[QOI]]
deps = ["ColorTypes", "FileIO", "FixedPointNumbers"]
git-tree-sha1 = "18e8f4d1426e965c7b532ddd260599e1510d26ce"
uuid = "4b34888f-f399-49d4-9bb3-47ed5cae4e65"
version = "1.0.0"

[[QuadGK]]
deps = ["DataStructures", "LinearAlgebra"]
git-tree-sha1 = "78aadffb3efd2155af139781b8a8df1ef279ea39"
uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
version = "2.4.2"

[[REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[Random]]
deps = ["Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[Ratios]]
deps = ["Requires"]
git-tree-sha1 = "01d341f502250e81f6fec0afe662aa861392a3aa"
uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439"
version = "0.4.2"

[[Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"

[[RelocatableFolders]]
deps = ["SHA", "Scratch"]
git-tree-sha1 = "cdbd3b1338c72ce29d9584fdbe9e9b70eeb5adca"
uuid = "05181044-ff0b-4ac5-8273-598c1e38db00"
version = "0.1.3"

[[Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.3.0"

[[Rmath]]
deps = ["Random", "Rmath_jll"]
git-tree-sha1 = "bf3188feca147ce108c76ad82c2792c57abe7b1f"
uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa"
version = "0.7.0"

[[Rmath_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "68db32dff12bb6127bac73c209881191bf0efbb7"
uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f"
version = "0.3.0+0"

[[SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"

[[SIMD]]
git-tree-sha1 = "39e3df417a0dd0c4e1f89891a281f82f5373ea3b"
uuid = "fdea26ae-647d-5447-a871-4b548cad5224"
version = "3.4.0"

[[ScanByte]]
deps = ["Libdl", "SIMD"]
git-tree-sha1 = "9cc2955f2a254b18be655a4ee70bc4031b2b189e"
uuid = "7b38b023-a4d7-4c5e-8d43-3f3097f304eb"
version = "0.3.0"

[[Scratch]]
deps = ["Dates"]
git-tree-sha1 = "0b4b7f1393cff97c33891da2a0bf69c6ed241fda"
uuid = "6c6a2e73-6563-6170-7368-637461726353"
version = "1.1.0"

[[Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[ShaderAbstractions]]
deps = ["ColorTypes", "FixedPointNumbers", "GeometryBasics", "LinearAlgebra", "Observables", "StaticArrays", "StructArrays", "Tables"]
git-tree-sha1 = "0d97c895406b552bed78f3a1fe9925248e908ae2"
uuid = "65257c39-d410-5151-9873-9b3e5be5013e"
version = "0.2.8"

[[SharedArrays]]
deps = ["Distributed", "Mmap", "Random", "Serialization"]
uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383"

[[Showoff]]
deps = ["Dates", "Grisu"]
git-tree-sha1 = "91eddf657aca81df9ae6ceb20b959ae5653ad1de"
uuid = "992d4aef-0814-514b-bc4d-f2e9a6c4116f"
version = "1.0.3"

[[SignedDistanceFields]]
deps = ["Random", "Statistics", "Test"]
git-tree-sha1 = "d263a08ec505853a5ff1c1ebde2070419e3f28e9"
uuid = "73760f76-fbc4-59ce-8f25-708e95d2df96"
version = "0.4.0"

[[SimpleTraits]]
deps = ["InteractiveUtils", "MacroTools"]
git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231"
uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
version = "0.9.4"

[[Sixel]]
deps = ["Dates", "FileIO", "ImageCore", "IndirectArrays", "OffsetArrays", "REPL", "libsixel_jll"]
git-tree-sha1 = "8fb59825be681d451c246a795117f317ecbcaa28"
uuid = "45858cf5-a6b0-47a3-bbea-62219f50df47"
version = "0.1.2"

[[Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[SortingAlgorithms]]
deps = ["DataStructures"]
git-tree-sha1 = "b3363d7460f7d098ca0912c69b082f75625d7508"
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
version = "1.0.1"

[[SparseArrays]]
deps = ["LinearAlgebra", "Random"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[[SpecialFunctions]]
deps = ["ChainRulesCore", "IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
git-tree-sha1 = "5ba658aeecaaf96923dce0da9e703bd1fe7666f9"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "2.1.4"

[[StackViews]]
deps = ["OffsetArrays"]
git-tree-sha1 = "46e589465204cd0c08b4bd97385e4fa79a0c770c"
uuid = "cae243ae-269e-4f55-b966-ac2d0dc13c15"
version = "0.1.1"

[[Static]]
deps = ["IfElse"]
git-tree-sha1 = "00b725fffc9a7e9aac8850e4ed75b4c1acbe8cd2"
uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3"
version = "0.5.5"

[[StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "74fb527333e72ada2dd9ef77d98e4991fb185f04"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.4.1"

[[Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[[StatsAPI]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "c3d8ba7f3fa0625b062b82853a7d5229cb728b6b"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.2.1"

[[StatsBase]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "8977b17906b0a1cc74ab2e3a05faa16cf08a8291"
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
version = "0.33.16"

[[StatsFuns]]
deps = ["ChainRulesCore", "HypergeometricFunctions", "InverseFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"]
git-tree-sha1 = "25405d7016a47cf2bd6cd91e66f4de437fd54a07"
uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
version = "0.9.16"

[[StructArrays]]
deps = ["Adapt", "DataAPI", "StaticArrays", "Tables"]
git-tree-sha1 = "57617b34fa34f91d536eb265df67c2d4519b8b98"
uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
version = "0.6.5"

[[SuiteSparse]]
deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"]
uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9"

[[TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[[TableTraits]]
deps = ["IteratorInterfaceExtensions"]
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
version = "1.0.1"

[[Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"]
git-tree-sha1 = "bb1064c9a84c52e277f1096cf41434b675cd368b"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.6.1"

[[Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"

[[TensorCore]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6"
uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50"
version = "0.1.1"

[[Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[[TiffImages]]
deps = ["ColorTypes", "DataStructures", "DocStringExtensions", "FileIO", "FixedPointNumbers", "IndirectArrays", "Inflate", "OffsetArrays", "PkgVersion", "ProgressMeter", "UUIDs"]
git-tree-sha1 = "991d34bbff0d9125d93ba15887d6594e8e84b305"
uuid = "731e570b-9d59-4bfa-96dc-6df516fadf69"
version = "0.5.3"

[[TranscodingStreams]]
deps = ["Random", "Test"]
git-tree-sha1 = "216b95ea110b5972db65aa90f88d8d89dcb8851c"
uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa"
version = "0.9.6"

[[UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[[UnicodeFun]]
deps = ["REPL"]
git-tree-sha1 = "53915e50200959667e78a92a418594b428dffddf"
uuid = "1cfade01-22cf-5700-b092-accc4b62d6e1"
version = "0.4.1"

[[WoodburyMatrices]]
deps = ["LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "de67fa59e33ad156a590055375a30b23c40299d3"
uuid = "efce3f68-66dc-5838-9240-27a6d6f5f9b6"
version = "0.5.5"

[[XML2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "1acf5bdf07aa0907e0a37d3718bb88d4b687b74a"
uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a"
version = "2.9.12+0"

[[XSLT_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "Pkg", "XML2_jll", "Zlib_jll"]
git-tree-sha1 = "91844873c4085240b95e795f692c4cec4d805f8a"
uuid = "aed1982a-8fda-507f-9586-7b0439959a61"
version = "1.1.34+0"

[[Xorg_libX11_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll", "Xorg_xtrans_jll"]
git-tree-sha1 = "5be649d550f3f4b95308bf0183b82e2582876527"
uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc"
version = "1.6.9+4"

[[Xorg_libXau_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4e490d5c960c314f33885790ed410ff3a94ce67e"
uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec"
version = "1.0.9+4"

[[Xorg_libXcursor_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "12e0eb3bc634fa2080c1c37fccf56f7c22989afd"
uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724"
version = "1.2.0+4"

[[Xorg_libXdmcp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4fe47bd2247248125c428978740e18a681372dd4"
uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05"
version = "1.1.3+4"

[[Xorg_libXext_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "b7c0aa8c376b31e4852b360222848637f481f8c3"
uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3"
version = "1.3.4+4"

[[Xorg_libXfixes_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "0e0dc7431e7a0587559f9294aeec269471c991a4"
uuid = "d091e8ba-531a-589c-9de9-94069b037ed8"
version = "5.0.3+4"

[[Xorg_libXi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXfixes_jll"]
git-tree-sha1 = "89b52bc2160aadc84d707093930ef0bffa641246"
uuid = "a51aa0fd-4e3c-5386-b890-e753decda492"
version = "1.7.10+4"

[[Xorg_libXinerama_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll"]
git-tree-sha1 = "26be8b1c342929259317d8b9f7b53bf2bb73b123"
uuid = "d1454406-59df-5ea1-beac-c340f2130bc3"
version = "1.1.4+4"

[[Xorg_libXrandr_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "34cea83cb726fb58f325887bf0612c6b3fb17631"
uuid = "ec84b674-ba8e-5d96-8ba1-2a689ba10484"
version = "1.5.2+4"

[[Xorg_libXrender_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "19560f30fd49f4d4efbe7002a1037f8c43d43b96"
uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa"
version = "0.9.10+4"

[[Xorg_libpthread_stubs_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "6783737e45d3c59a4a4c4091f5f88cdcf0908cbb"
uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74"
version = "0.1.0+3"

[[Xorg_libxcb_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"]
git-tree-sha1 = "daf17f441228e7a3833846cd048892861cff16d6"
uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b"
version = "1.13.0+3"

[[Xorg_xtrans_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "79c31e7844f6ecf779705fbc12146eb190b7d845"
uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10"
version = "1.4.0+3"

[[Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"

[[isoband_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "51b5eeb3f98367157a7a12a1fb0aa5328946c03c"
uuid = "9a68df92-36a6-505f-a73e-abb412b6bfb4"
version = "0.2.3+0"

[[libass_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "5982a94fcba20f02f42ace44b9894ee2b140fe47"
uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0"
version = "0.15.1+0"

[[libfdk_aac_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "daacc84a041563f965be61859a36e17c4e4fcd55"
uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280"
version = "2.0.2+0"

[[libpng_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "94d180a6d2b5e55e447e2d27a29ed04fe79eb30c"
uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f"
version = "1.6.38+0"

[[libsixel_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "78736dab31ae7a53540a6b752efc61f77b304c5b"
uuid = "075b6546-f08a-558a-be8f-8157d0f608a5"
version = "1.8.6+1"

[[libvorbis_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg"]
git-tree-sha1 = "b910cb81ef3fe6e78bf6acee440bda86fd6ae00c"
uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a"
version = "1.3.7+1"

[[nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"

[[p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"

[[x264_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4fea590b89e6ec504593146bf8b988b2c00922b2"
uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a"
version = "2021.5.5+0"

[[x265_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "ee567a171cce03570d77ad3a43e90218e38937a9"
uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76"
version = "3.5.0+0"
"""

# ╔═╡ Cell order:
# ╠═560feed0-98bd-11ec-1e02-cd284b028586
# ╠═81730fe7-49e0-4d4b-8155-d41fd3849fc5
# ╠═3b3218d8-917e-4668-8044-16eb03ef77c4
# ╠═ed6351cb-9382-437a-abb0-bd10782a07e8
# ╠═faf06569-a7d6-436e-a522-575758eab31c
# ╠═a76433a2-d967-4be7-8ca8-8f5a24ab6cc5
# ╠═e53a587b-9b65-4976-a708-e2c00361460c
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002

selfloop placement for digraph is broken

image

    g = SimpleDiGraph(3)
    add_edge!(g, 1, 2)
    add_edge!(g, 2, 3)
    add_edge!(g, 3, 1)
    add_edge!(g, 1, 1)
    add_edge!(g, 2, 2)
    add_edge!(g, 3, 3)

    f, ax, p  = graphplot(g)

Add one label to multiple edges

I have multiple edges that shall have the same label. Instead of repeatedly displaying the label for each of the edges, is it possible to show only one label for all of them together?

Example from the docs:
grafik
I might want to remove the labels 3, 2 and 8 and only show a label "top side" that is positioned in the middle (distance-wise) of the three edges.

I assume that this would only be possible if we provide a list of those nodes that belong to each other (e.g. [2,3,8] in the example above). Assuming we have such a list, would it then be possible to display a combined label for all three edges?

Approaching this in a naive way, I would just set the label of edges 3 and 8 to "" and the label of edge 2 to "top side". This isn't really a good solution though because it wouldn't necessarily place the label in the middle along the three edges and also wouldn't work for even numbers of edges.

Multigraph support

Hi @hexaeder,

Thanks again for the great package. We are currently using it very successfully as a backend for visualizing tensor networks in ITensors.jl (through add-on packages like ITensorGLMakie).

Do you support or plan to support plotting multigraphs? I see that Plots.jl has some support: https://docs.juliaplots.org/latest/graphrecipes/examples/#Multigraphs and there is a Multigraphs.jl package, but over all the support for multigraphs is a bit lacking in the Julia ecosystem. I imagine it doesn't need a special graph type, just some extra keyword arguments passed to graphplot optionally indicating the multiplicity (and maybe directions) of the edges.

For the application of tensor network visualization, directed multigraphs are quite common. Right now, out of simplicity, I just handle the multigraph case with a simple graph that has edge labels indicating there are multiple edges, but ultimately it would be nice to visualize multigraphs directly.

Time permitting, I would be interested in helping out with adding that as a feature (though I am not so familiar with the design and internals of Makie).

Cheers,
Matt

Question: edge indices

Is there a particular reason why edges are being referenced with the integer index rather than the edge itself (or src, dst tuple)? I'm curious because Graphs.jl doesn't support indexed edges and there is some debate there on this: JuliaGraphs/Graphs.jl#127

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.