GraphMakie
This is the Documentation for GraphMakie.
This Package consists of two parts: a plot recipe for graphs types from LightGraphs.jl and some helper functions to add interactions to those plots.
There are also plot examples and interaction examples.
graphplot
recipe
GraphMakie.graphplot
— Functiongraphplot(graph::AbstractGraph)
graphplot!(ax, graph::AbstractGraph)
Creates a plot of the network graph
. Consists of multiple steps:
- Layout the nodes: the
layout
attribute is has to be a functionf(adj_matrix)::pos
wherepos
is either an array ofPoint2f0
or(x, y)
tuples - plot edges as
linesegments
-plot - plot nodes as
scatter
-plot - if
nlabels!=nothing
plot node labels astext
-plot - if
elabels!=nothing
plot edge labels astext
-plot
The main attributes for the subplots are exposed as attributes for graphplot
. Additional attributes for the scatter
, linesegments
and text
plots can be provided as a named tuples to node_attr
, edge_attr
, nlabels_attr
and elabels_attr
.
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.
Attributes
Available attributes and their defaults for Combined{GraphMakie.graphplot, T} where T
are:
edge_attr Attributes with 0 entries
edge_color :black
edge_width 1.0
elabels "nothing"
elabels_align (:center, :bottom)
elabels_attr Attributes with 0 entries
elabels_color :black
elabels_distance 0.0
elabels_offset Float32[0.0, 0.0]
elabels_opposite Int64[]
elabels_rotation "nothing"
elabels_shift 0.0
elabels_textsize 20
layout NetworkLayout.Spring.layout
nlabels "nothing"
nlabels_align (:left, :bottom)
nlabels_attr Attributes with 0 entries
nlabels_color :black
nlabels_offset Float32[0.0, 0.0]
nlabels_textsize 20
node_attr Attributes with 0 entries
node_color :gray65
node_marker Circle{T} where T
node_size 8
Interactions
GraphMakie.jl
provides some helper functions to register interactions to your graph plot. There are special Interaction types for hovering, clicking and draging nodes and edges. For more information on the axis interaction please consult the Makie.jl
docs.
The general idea is to create some handler type, provide some action function and register it as an interaction with the axes.
Click interactions
GraphMakie.NodeClickHandler
— FunctionNodeClickHandler(fun)
Initializes ClickHandler
for nodes. Calls function
fun(idx, event, axis)
on left-click events where idx
is the node index.
Example
julia> using AbstractPlotting.Colors
julia> g = wheel_digraph(10)
julia> f, ax, p = graphplot(g, node_size=30, node_color=[colorant"red" for i in 1:nv(g)])
julia> function action(idx, event, axis)
p.node_color[][idx] = rand(RGB)
p.node_color[] = p.node_color[]
end
julia> register_interaction!(ax, :nodeclick, NodeClickHandler(action))
GraphMakie.EdgeClickHandler
— FunctionEdgeClickHandler(fun)
Initializes ClickHandler
for edges. Calls function
fun(idx, event, axis)
on left-click events where idx
is the edge index.
Example
julia> using AbstractPlotting.Colors
julia> g = wheel_digraph(10)
julia> f, ax, p = graphplot(g, edge_width=4, edge_color=[colorant"black" for i in 1:ne(g)])
julia> function action(idx, event, axis)
p.edge_color[][idx] = rand(RGB)
p.edge_color[] = p.edge_color[]
end
julia> register_interaction!(ax, :edgeclick, EdgeClickHandler(action))
Hover interactions
GraphMakie.NodeHoverHandler
— FunctionNodeHoverHandler(fun)
Initializes HoverHandler
for nodes. Calls function
fun(hoverstate, idx, event, axis)
with hoverstate=true
on hover and false
at the end of hover. idx
is the node index.
Example
julia> g = wheel_digraph(10)
julia> f, ax, p = graphplot(g, node_size = [20 for i in 1:nv(g)])
julia> function action(state, idx, event, axis)
p.node_size[][idx] = state ? 40 : 20
p.node_size[] = p.node_size[] #trigger observable
end
julia> register_interaction!(ax, :nodehover, NodeHoverHandler(action))
GraphMakie.EdgeHoverHandler
— FunctionEdgeHoverHandler(fun)
Initializes HoverHandler
for edges. Calls function
fun(hoverstate, idx, event, axis)
with hoverstate=true
on hover and false
at the end of hover. idx
is the edge index.
Example
julia> g = wheel_digraph(10)
julia> f, ax, p = graphplot(g, edge_width = [3.0 for i in 1:ne(g)])
julia> function action(state, idx, event, axis)
p.edge_width[][idx] = state ? 6.0 : 3.0
p.edge_width[] = p.edge_width[] #trigger observable
end
julia> register_interaction!(ax, :edgehover, EdgeHoverHandler(action))
Drag interactions
GraphMakie.NodeDragHandler
— FunctionNodeDragHandler(fun)
Initializes DragHandler
for Nodes. Calls function
fun(dragstate, idx, event, axis)
where dragstate=true
during the drag and false
at the end of the drag, the last time fun
is triggered. idx
is the node index.
Example
julia> g = wheel_digraph(10)
julia> f, ax, p = graphplot(g, node_size=20)
julia> deregister_interaction!(ax, :rectanglezoom)
julia> function action(state, idx, event, axis)
p[:node_positions][][idx] = event.data
p[:node_positions][] = p[:node_positions][]
end
julia> register_interaction!(ax, :nodedrag, NodeDragHandler(action))
GraphMakie.EdgeDragHandler
— FunctionEdgeDragHandler(fun)
Initializes DragHandler
for Edges. Calls function
fun(dragstate, idx, event, axis)
where dragstate=true
during the drag and false
at the end of the drag, the last time fun
is triggered. idx
is the edge index.
Example
julia> g = wheel_digraph(10)
julia> f, ax, p = graphplot(g, edge_width=3)
julia> deregister_interaction!(ax, :rectanglezoom)
julia> mutable struct EdgeDragAction
init::Union{Nothing, Point2f0} # save click position
src::Union{Nothing, Point2f0} # save src vertex position
dst::Union{Nothing, Point2f0} # save dst vertex position
EdgeDragAction() = new(nothing, nothing, nothing)
end
julia> function (action::EdgeDragAction)(state, idx, event, axis)
edge = collect(edges(g))[idx]
if state == true
if action.src===action.dst===action.init===nothing
action.init = event.data
action.src = p[:node_positions][][edge.src]
action.dst = p[:node_positions][][edge.dst]
end
offset = event.data - action.init
p[:node_positions][][edge.src] = action.src + offset
p[:node_positions][][edge.dst] = action.dst + offset
p[:node_positions][] = p[:node_positions][] # trigger change
elseif state == false
action.src = action.dst = action.init = nothing
end
end
julia> handler = EdgeDragHandler(EdgeDragAction())
julia> register_interaction!(ax, :edgedrag, handler)