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

support changing plot size (included in PR #186) #182

Closed
wants to merge 15 commits into from
Closed
6 changes: 6 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 All @@ -183,6 +187,8 @@ gplot(h)
+ `arrowangleoffset` Angular width in radians for the arrows. Default: `π/9 (20 degrees)`
+ `linetype` Type of line used for edges ("straight", "curve"). Default: "straight"
+ `outangle` Angular width in radians for the edges (only used if `linetype = "curve`). Default: `π/5 (36 degrees)`
+ `plot_size` Tuple of measures for width x height of plot area. Default: `(sqrt(2)*10cm, 10cm)`
+ `leftpad, rightpad, toppad, bottompad` Padding for the plot margins. Default: `0mm`

# Reporting Bugs

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
73 changes: 51 additions & 22 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 @@ -94,9 +106,18 @@ Type of line used for edges ("straight", "curve"). Default: "straight"
Angular width in radians for the edges (only used if `linetype = "curve`).
Default: `π/5 (36 degrees)`

`plot_size`
Tuple of measures for width x height for plot area. Default: `(sqrt(2)*10cm, 10cm)`

`leftpad, rightpad, toppad, bottompad`
Padding for the plot margins. Default: `0mm`
"""
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 All @@ -120,7 +141,13 @@ function gplot(g::AbstractGraph{T},
arrowlengthfrac = is_directed(g) ? 0.1 : 0.0,
arrowangleoffset = π / 9,
linetype = "straight",
outangle = π / 5) where {T <:Integer, R1 <: Real, R2 <: Real}
outangle = π / 5,
plot_size = (sqrt(2)*10cm, 10cm),
leftpad = 0mm,
rightpad = 0mm,
toppad = 0mm,
bottompad = 0mm
) where {T <:Integer, R1 <: Real, R2 <: Real}

length(locs_x_in) != length(locs_y_in) && error("Vectors must be same length")
N = nv(g)
Expand Down Expand Up @@ -206,33 +233,35 @@ 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)),
# Set plot_size
if length(plot_size) != 2 || !isa(plot_size[1], Compose.AbsoluteLength) || !isa(plot_size[2], Compose.AbsoluteLength)
error("`plot_size` must be a Tuple of lengths")
end
Compose.set_default_graphic_size(plot_size...)

# Fix title offset
title_offset = isempty(title) ? 0 : 0.1*title_size/4

# Build figure
compose(context(units=UnitBox(-1.2, -1.2 - title_offset, +2.4, +2.4 + title_offset; leftpad, rightpad, toppad, bottompad)),
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