Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make self-loop edges curved (included in PR #186) #184

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ gplot(h)

# Keyword Arguments
+ `layout` Layout algorithm: `random_layout`, `circular_layout`, `spring_layout`, `shell_layout`, `stressmajorize_layout`, `spectral_layout`. Default: `spring_layout`
+ `title` Plot title. Default: `""`
+ `title_color` Plot title color. Default: `colorant"black"`
+ `title_size` Plot title size. Default: `4.0`
+ `font_family` Font family for all text. Default: `"Helvetica"`
+ `NODESIZE` Max size for the nodes. Default: `3.0/sqrt(N)`
+ `nodesize` Relative size for the nodes, can be a Vector. Default: `1.0`
+ `nodelabel` Labels for the vertices, a Vector or nothing. Default: `nothing`
Expand Down
2 changes: 2 additions & 0 deletions src/GraphPlot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module GraphPlot

using Compose # for plotting features
using Graphs
using LinearAlgebra
using SparseArrays

const gadflyjs = joinpath(dirname(Base.source_path()), "gadfly.js")

Expand Down
18 changes: 9 additions & 9 deletions src/layout.jl
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ julia> locs_x, locs_y = spring_layout(g)
```
"""
function spring_layout(g::AbstractGraph,
locs_x=2*rand(nv(g)).-1.0,
locs_y=2*rand(nv(g)).-1.0;
locs_x::Vector{R1}=2*rand(nv(g)).-1.0,
locs_y::Vector{R2}=2*rand(nv(g)).-1.0;
C=2.0,
MAXITER=100,
INITTEMP=2.0)
INITTEMP=2.0) where {R1 <: Real, R2 <: Real}

nvg = nv(g)
adj_matrix = adjacency_matrix(g)
Expand Down Expand Up @@ -174,7 +174,7 @@ end

using Random: MersenneTwister

function spring_layout(g::AbstractGraph, seed::Integer, kws...)
function spring_layout(g::AbstractGraph, seed::Integer; kws...)
rng = MersenneTwister(seed)
spring_layout(g, 2 .* rand(rng, nv(g)) .- 1.0, 2 .* rand(rng,nv(g)) .- 1.0; kws...)
end
Expand Down Expand Up @@ -205,20 +205,20 @@ function shell_layout(g, nlist::Union{Nothing, Vector{Vector{Int}}} = nothing)
if nv(g) == 1
return [0.0], [0.0]
end
if nlist == nothing
if isnothing(nlist)
nlist = [collect(1:nv(g))]
end
radius = 0.0
if length(nlist[1]) > 1
radius = 1.0
end
locs_x = Float64[]
locs_y = Float64[]
locs_x = zeros(nv(g))
locs_y = zeros(nv(g))
for nodes in nlist
# Discard the extra angle since it matches 0 radians.
θ = range(0, stop=2pi, length=length(nodes)+1)[1:end-1]
append!(locs_x, radius*cos.(θ))
append!(locs_y, radius*sin.(θ))
locs_x[nodes] = radius*cos.(θ)
locs_y[nodes] = radius*sin.(θ)
radius += 1.0
end
return locs_x, locs_y
Expand Down
46 changes: 46 additions & 0 deletions src/lines.jl
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,49 @@ function curveedge(x1, y1, x2, y2, θ, outangle, d; k=0.5)

return [(x1,y1) (xc1, yc1) (xc2, yc2) (x2, y2)]
end

function build_curved_edges(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset, outangle)
if arrowlengthfrac > 0.0
curves_cord, arrows_cord = graphcurve(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset, outangle)
curves = curve(curves_cord[:,1], curves_cord[:,2], curves_cord[:,3], curves_cord[:,4])
carrows = line(arrows_cord)
else
curves_cord = graphcurve(g, locs_x, locs_y, nodesize, outangle)
curves = curve(curves_cord[:,1], curves_cord[:,2], curves_cord[:,3], curves_cord[:,4])
carrows = nothing
end

return curves, carrows
end

function build_straight_edges(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset)
if arrowlengthfrac > 0.0
lines_cord, arrows_cord = graphline(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset)
lines = line(lines_cord)
larrows = line(arrows_cord)
else
lines_cord = graphline(g, locs_x, locs_y, nodesize)
lines = line(lines_cord)
larrows = nothing
end

return lines, larrows
end

function build_straight_curved_edges(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset, outangle)
A = adjacency_matrix(g) #adjacency matrix
B = spdiagm(diag(A)) #diagonal matrix (self-loops)
A[diagind(A)] .= 0 #set diagonal elements to 0 (remove self-loops)
if is_directed(g)
g1 = SimpleDiGraph(A)
g2 = SimpleDiGraph(B)
else
g1 = SimpleGraph(A)
g2 = SimpleGraph(B)
end

lines, larrows = build_straight_edges(g1, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset)
curves, carrows = build_curved_edges(g2, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset, outangle)

return lines, larrows, curves, carrows
end
51 changes: 30 additions & 21 deletions src/plot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ Layout algorithm. Currently can be one of [`random_layout`,
`spectral_layout`].
Default: `spring_layout`

`title`
Plot title. Default: `""`

`title_color`
Plot title color. Default: `colorant"black"`

`title_size`
Plot title size. Default: `4.0`

`font_family`
Font family for all text. Default: `"Helvetica"`

`NODESIZE`
Max size for the nodes. Default: `3.0/sqrt(N)`

Expand Down Expand Up @@ -97,6 +109,10 @@ Default: `π/5 (36 degrees)`
"""
function gplot(g::AbstractGraph{T},
locs_x_in::Vector{R1}, locs_y_in::Vector{R2};
title = "",
title_color = colorant"black",
title_size = 4.0,
font_family = "Helvetica",
nodelabel = nothing,
nodelabelc = colorant"black",
nodelabelsize = 1.0,
Expand Down Expand Up @@ -206,33 +222,26 @@ function gplot(g::AbstractGraph{T},
end

# Create lines and arrow heads
lines, arrows = nothing, nothing
lines, larrows = nothing, nothing
curves, carrows = nothing, nothing
if linetype == "curve"
if arrowlengthfrac > 0.0
curves_cord, arrows_cord = graphcurve(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset, outangle)
lines = curve(curves_cord[:,1], curves_cord[:,2], curves_cord[:,3], curves_cord[:,4])
arrows = line(arrows_cord)
else
curves_cord = graphcurve(g, locs_x, locs_y, nodesize, outangle)
lines = curve(curves_cord[:,1], curves_cord[:,2], curves_cord[:,3], curves_cord[:,4])
end
curves, carrows = build_curved_edges(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset, outangle)
elseif has_self_loops(g)
lines, larrows, curves, carrows = build_straight_curved_edges(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset, outangle)
else
if arrowlengthfrac > 0.0
lines_cord, arrows_cord = graphline(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset)
lines = line(lines_cord)
arrows = line(arrows_cord)
else
lines_cord = graphline(g, locs_x, locs_y, nodesize)
lines = line(lines_cord)
end
lines, larrows = build_straight_edges(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset)
end

compose(context(units=UnitBox(-1.2, -1.2, +2.4, +2.4)),
compose(context(), texts, fill(nodelabelc), stroke(nothing), fontsize(nodelabelsize)),
title_offset = isempty(title) ? 0 : 0.1*title_size/4
compose(context(units=UnitBox(-1.2, -1.2 - title_offset, +2.4, +2.4 + title_offset)),
compose(context(), text(0, -1.2 - title_offset/2, title, hcenter, vcenter), fill(title_color), fontsize(title_size), font(font_family)),
compose(context(), texts, fill(nodelabelc), fontsize(nodelabelsize), font(font_family)),
compose(context(), nodes, fill(nodefillc), stroke(nodestrokec), linewidth(nodestrokelw)),
compose(context(), edgetexts, fill(edgelabelc), stroke(nothing), fontsize(edgelabelsize)),
compose(context(), arrows, stroke(edgestrokec), linewidth(edgelinewidth)),
compose(context(), lines, stroke(edgestrokec), fill(nothing), linewidth(edgelinewidth)))
compose(context(), larrows, stroke(edgestrokec), linewidth(edgelinewidth)),
compose(context(), carrows, stroke(edgestrokec), linewidth(edgelinewidth)),
compose(context(), lines, stroke(edgestrokec), fill(nothing), linewidth(edgelinewidth)),
compose(context(), curves, stroke(edgestrokec), fill(nothing), linewidth(edgelinewidth)))
end

function gplot(g; layout::Function=spring_layout, keyargs...)
Expand Down