Skip to content

Commit

Permalink
Merge pull request #89 from filchristou/defdictattrs
Browse files Browse the repository at this point in the history
(Default)Dict for some attributes
  • Loading branch information
hexaeder committed Jun 20, 2023
2 parents 7c2e706 + e9135ba commit d9eb254
Show file tree
Hide file tree
Showing 26 changed files with 244 additions and 53 deletions.
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ authors = ["Simon Danisch", "Hans Würfel"]
version = "0.5.4"

[deps]
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
NetworkLayout = "46757867-2c16-5918-afeb-47bfcb05e46a"
PolynomialRoots = "3a141323-8675-5d76-9d11-e1df1406c778"
SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"

[compat]
Expand Down
Binary file added assets/reftests.jl-25.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-26.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-27.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-28.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-29.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-30.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-31.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-33.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-34.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-35.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-36.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-37.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-38.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-39.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-40.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-41.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-42.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/reftests.jl-43.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[deps]
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
Cbc = "9961bab8-2fa3-5c5a-9d89-47fab24efd76"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
GraphMakie = "1ecd5474-83a3-4783-bb4f-06765db800d2"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
Expand Down
95 changes: 94 additions & 1 deletion docs/examples/reftests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ testing. They might be interesting but they are most probably not.
=#
# ## Test different `nlabels_align` modes
using Graphs, GraphMakie, CairoMakie, NetworkLayout
import DataStructures: DefaultDict

CairoMakie.activate!(type="png") # hide
set_theme!(resolution=(400, 400)) #hide
g = SimpleGraph(9)
Expand Down Expand Up @@ -194,4 +196,95 @@ p[:ilabels_fontsize][] = 10
@save_reference fig

p[:node_color][] = :red
@save_reference fig
@save_reference fig

# ## Changes of node and label sizes
gc = circular_ladder_graph(5);
ons = Observable(30);
onf = Observable(30);
fig,ax,p = graphplot(gc; nlabels=repr.(vertices(gc)), node_size=ons, nlabels_fontsize=onf)
@save_reference fig

# Change node size
ons[] = 10; # check changes
@save_reference fig

# Change label font size
onf[] = 10; # check changes
@save_reference fig


# Do the same with a `Dict`
onf = Observable(Dict(1=>30, 10=>30));
ons = Observable(Dict(1=>30, 10=>30));
fig,ax,p = graphplot(gc; nlabels=repr.(vertices(gc)), node_size=ons, nlabels_fontsize=onf)
@save_reference fig

# Change label font size
onf[] = Dict(7=>30); # check changes
@save_reference fig

# Change node size
ons[] = Dict(7=>30); # check changes
@save_reference fig

# Do the same with a `DefaultDict`
ons = Observable(DefaultDict(70, 1=>30, 10=>30));
onf = Observable(DefaultDict(70, 1=>30, 10=>30));
fig,ax,p = graphplot(gc; nlabels=repr.(vertices(gc)), node_size=ons, nlabels_fontsize=onf)
@save_reference fig

# Change node size
ons[] = DefaultDict(20, 10=>70); # check changes
@save_reference fig

# Change label font size
onf[] = DefaultDict(20, 10=>70); # check changes
@save_reference fig

# ## Dict and DefaultDict
# Test out argument functionality with `Dict` and `DefaultDict`
# First with a normal `Dict`
gc = circular_ladder_graph(5);
fig,ax,p = graphplot(gc, nlabels=Dict(1=>"One", 2 => "Two"))
@save_reference fig

# And also with a `DefaultDict`
fig,ax,p = graphplot(gc, nlabels=DefaultDict("Unknown", 1=>"One", 2 => "Two"))
@save_reference fig

# ## Use Dict{Edge} for edge arguments
fig,ax,p = graphplot(gc, edge_color=Dict(Edge(7,8)=>:blue))
@save_reference fig

# try out also the DefaultDict
fig,ax,p = graphplot(gc, edge_color=DefaultDict(:green, Edge(7,8)=>:blue))
@save_reference fig

# Of course you can still use integers labeling
ind = findfirst(==(Edge(7,8)) , collect(edges(gc)))
fig,ax,p = graphplot(gc, edge_color=DefaultDict(:green, ind=>:blue))
@save_reference fig

# The same can be done with all enumerations of edge arguments
fig,ax,p = graphplot(gc, elabels=DefaultDict("Unknown", Edge(1,2)=>"1-2", Edge(7,8) => "7-8"))
@save_reference fig

# directed and undirected graphs are handled appropriately.
# For example for directed graphs
gcd = SimpleDiGraph(gc)
fig,ax,p = graphplot(gcd, elabels=DefaultDict("Unknown", Edge(8,7)=>"8-7", Edge(2,7) => "2-7"), nlabels=repr.(vertices(gcd)))
@save_reference fig

# and non-directed graphs
fig,ax,p = graphplot(gc, elabels=DefaultDict("Unknown", Edge(8,7)=>"8-7", Edge(2,7) => "2-7"), nlabels=repr.(vertices(gc)))
@save_reference fig

# Test edge-specific updates
ec = Observable(Dict(Edge(8,7)=>:blue))
fig,ax,p = graphplot(gc, edge_color=ec, nlabels=repr.(vertices(gc)))
@save_reference fig

# update `Observable`
ec[] = Dict(Edge(7,2)=> :green)
@save_reference fig
7 changes: 7 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ There are also [plot examples](generated/plots.md) and [interaction examples](ge
graphplot
```

## Passing arguments
The recipe can handle a range of argument types.
For all the arguments that support a collection of configurations per element, you pass-in a `Vector`.
However you can also pass in a `Dict` or a `DefaultDict` to only specify a configuration for a specific element of interest, while the rest get the default value.
The `keys` of the `Dict`ionaries are the `Int` index of the element or the `Edge` when reasonable.
See some demonstration on [Changes of node and label sizes](@ref), [Dict and DefaultDict](@ref) and [Use Dict{Edge} for edge arguments](@ref).

## Network Layouts
The layout algorithms are provided by [`NetworkLayout.jl`](https://github.com/JuliaGraphs/NetworkLayout.jl). See
the [docs](https://juliagraphs.org/NetworkLayout.jl/stable/) for a list of available layouts.
Expand Down
2 changes: 2 additions & 0 deletions src/GraphMakie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ using NetworkLayout
using Graphs
using Makie
using LinearAlgebra
using SimpleTraits

import Makie: DocThemer, ATTRIBUTES, project, automatic
import DataStructures: DefaultDict, DefaultOrderedDict

include("beziercurves.jl")
include("recipes.jl")
Expand Down
92 changes: 47 additions & 45 deletions src/recipes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ end

function Makie.plot!(gp::GraphPlot)
graph = gp[:graph]

dfth = default_theme(gp.parent, GraphPlot)

# create initial vertex positions, will be updated on changes to graph or layout
# make node_position-Observable available as named attribute from the outside
Expand Down Expand Up @@ -249,29 +251,29 @@ function Makie.plot!(gp::GraphPlot)

translate!(ilabels_plot, 0, 0, 1)

node_size = lift(ilabels_plot.plots[1][1], gp.ilabels_fontsize) do glyphcollections, ilabels_fontsize
node_size_m = lift(ilabels_plot.plots[1][1], gp.ilabels_fontsize) do glyphcollections, ilabels_fontsize
map(glyphcollections) do gc
rect = Rect2f(boundingbox(gc, Quaternion((1,0,0,0))))
norm(rect.widths) + 0.1 * ilabels_fontsize
end
end
else
node_size = @lift $(gp.node_size) === automatic ? scatter_theme.markersize[] : gp.node_size[]
node_size_m = @lift $(gp.node_size) === automatic ? scatter_theme.markersize[] : $(gp.node_size)
end

node_color = @lift if $(gp.node_color) === automatic
node_color_m = @lift if $(gp.node_color) === automatic
gp.ilabels[] !== nothing ? :gray80 : scatter_theme.color[]
else
$(gp.node_color)
end

node_marker = @lift if $(gp.node_marker) === automatic
node_marker_m = @lift if $(gp.node_marker) === automatic
gp.ilabels[] !== nothing ? Circle : scatter_theme.marker[]
else
$(gp.node_marker)
end

node_strokewidth = @lift if $(gp.node_strokewidth) === automatic
node_strokewidth_m = @lift if $(gp.node_strokewidth) === automatic
gp.ilabels[] !== nothing ? 1.0 : scatter_theme.strokewidth[]
else
$(gp.node_strokewidth)
Expand All @@ -287,42 +289,43 @@ function Makie.plot!(gp::GraphPlot)

# plot edges
edge_plot = edgeplot!(gp, edge_paths;
color=gp.edge_color,
linewidth=gp.edge_width,
gp.edge_attr...)
color=prep_edge_attributes(gp.edge_color, graph, dfth.edge_color),
linewidth=prep_edge_attributes(gp.edge_width, graph, dfth.edge_width),
gp.edge_attr...)

# plot arrow heads
arrow_shift = lift(edge_paths, to_px, gp.arrow_shift, node_marker, node_size, gp.arrow_size) do paths, tpx, shift, nmarker, nsize, asize
update_arrow_shift(graph[], gp, paths, tpx, node_marker, node_size)
arrow_shift_m = lift(edge_paths, to_px, gp.arrow_shift, node_marker_m, node_size_m, gp.arrow_size) do paths, tpx, shift, nmarker, nsize, asize
update_arrow_shift(graph[], gp, paths, tpx, node_marker_m, node_size_m, shift)
end
arrow_pos = @lift if !isempty(edge_paths[])
broadcast(interpolate, edge_paths[], $arrow_shift)
broadcast(interpolate, edge_paths[], $arrow_shift_m)
else # if no edges return (empty) vector of points, broadcast yields Vector{Any} which can't be plotted
Vector{eltype(node_pos[])}()
end
arrow_rot = @lift if !isempty(edge_paths[])
Billboard(broadcast($to_angle, edge_paths[], $arrow_pos, arrow_shift[]))
Billboard(broadcast($to_angle, edge_paths[], $arrow_pos, $(arrow_shift_m)))
else
Billboard(Float32[])
end
arrow_show = @lift $(gp.arrow_show) === automatic ? Graphs.is_directed($graph) : $(gp.arrow_show)
arrow_show_m = @lift $(gp.arrow_show) === automatic ? Graphs.is_directed($graph) : $(gp.arrow_show)
arrow_heads = scatter!(gp,
arrow_pos;
marker = gp.arrow_marker,
markersize = gp.arrow_size,
color = gp.edge_color,
rotations = arrow_rot,
strokewidth = 0.0,
markerspace = :pixel,
visible = arrow_show,
gp.arrow_attr...)
arrow_pos;
marker = prep_edge_attributes(gp.arrow_marker, graph, dfth.arrow_marker),
markersize = prep_edge_attributes(gp.arrow_size, graph, dfth.arrow_size),
color=prep_edge_attributes(gp.edge_color, graph, dfth.edge_color),
rotations = arrow_rot,
strokewidth = 0.0,
markerspace = :pixel,
visible = arrow_show_m,
gp.arrow_attr...)

# plot vertices
vertex_plot = scatter!(gp, node_pos;
color=node_color,
marker=node_marker,
markersize=node_size,
strokewidth=node_strokewidth,
gp.node_attr...)
color=prep_vertex_attributes(node_color_m, graph, scatter_theme.color),
marker=prep_vertex_attributes(node_marker_m, graph, scatter_theme.marker),
markersize=prep_vertex_attributes(node_size_m, graph, scatter_theme.markersize),
strokewidth=prep_vertex_attributes(node_strokewidth_m, graph, scatter_theme.strokewidth),
gp.node_attr...)

# plot node labels
if gp.nlabels[] !== nothing
Expand All @@ -341,12 +344,12 @@ function Makie.plot!(gp::GraphPlot)
end

nlabels_plot = text!(gp, positions;
text=gp.nlabels,
align=gp.nlabels_align,
color=gp.nlabels_color,
offset=offset,
fontsize=gp.nlabels_fontsize,
gp.nlabels_attr...)
text=prep_vertex_attributes(gp.nlabels, graph, Observable("")),
align=prep_vertex_attributes(gp.nlabels_align, graph, dfth.nlabels_align),
color=prep_vertex_attributes(gp.nlabels_color, graph, dfth.nlabels_color),
offset=offset,
fontsize=prep_vertex_attributes(gp.nlabels_fontsize, graph, dfth.nlabels_fontsize),
gp.nlabels_attr...)
end

# plot edge labels
Expand Down Expand Up @@ -389,15 +392,14 @@ function Makie.plot!(gp::GraphPlot)
offsets = map(p -> Point(-p.data[2], p.data[1])/norm(p), tangent_px)
offsets .= elabels_distance_offset(graph[], gp.attributes) .* offsets
end

elabels_plot = text!(gp, positions;
text=gp.elabels,
rotation=rotation,
offset=offsets,
align=gp.elabels_align,
color=gp.elabels_color,
fontsize=gp.elabels_fontsize,
gp.elabels_attr...)
text=prep_edge_attributes(gp.elabels, graph, Observable("")),
rotation=rotation,
offset=offsets,
align=prep_edge_attributes(gp.elabels_align, graph, dfth.elabels_align),
color=prep_edge_attributes(gp.elabels_color, graph, dfth.elabels_color),
fontsize=prep_edge_attributes(gp.elabels_fontsize, graph, dfth.elabels_fontsize),
gp.elabels_attr...)
end

return gp
Expand Down Expand Up @@ -742,11 +744,11 @@ end
Checks `arrow_shift` attr so that `arrow_shift = :end` gets transformed so that the arrowhead for that edge
lands on the surface of the destination node.
"""
function update_arrow_shift(g, gp, edge_paths::Vector{<:AbstractPath{PT}}, to_px, node_markers, node_sizes) where {PT}
function update_arrow_shift(g, gp, edge_paths::Vector{<:AbstractPath{PT}}, to_px, node_markers, node_sizes, shift) where {PT}
arrow_shift = Vector{Float32}(undef, ne(g))

for (i,e) in enumerate(edges(g))
t = getattr(gp.arrow_shift, i, 0.5)
t = getattr(shift, i, 0.5)
if t === :end
j = dst(e)
p0 = getattr(gp.node_pos, j)
Expand All @@ -771,11 +773,11 @@ function update_arrow_shift(g, gp, edge_paths::Vector{<:AbstractPath{PT}}, to_px

return arrow_shift
end
function update_arrow_shift(g, gp, edge_paths::Vector{<:AbstractPath{<:Point3}}, to_px)
function update_arrow_shift(g, gp, edge_paths::Vector{<:AbstractPath{<:Point3}}, to_px, shift)
arrow_shift = Vector{Float32}(undef, ne(g))

for (i,e) in enumerate(edges(g))
t = getattr(gp.arrow_shift, i, 0.5)
t = getattr(shift, i, 0.5)
if t === :end #not supported because to_px does not give pixels in 3D space (would need to map 3D coordinates to pixels...?)
error("`arrow_shift = :end` not supported for 3D plots.")
end
Expand Down
Loading

0 comments on commit d9eb254

Please sign in to comment.