From 3368e8917e9308517511cb2778317a1edfd5032c Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Thu, 21 Jul 2022 17:20:53 -0500 Subject: [PATCH 01/18] Improve Readme and docstring -distinguish args, kwargs -add missing kwargs --- README.md | 45 ++++++++++++++++++++++++------------ src/plot.jl | 66 ++++++++++++++++++++++++++++++----------------------- 2 files changed, 68 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 63d836a..f5438ca 100644 --- a/README.md +++ b/README.md @@ -133,8 +133,8 @@ gplot(g, linetype="curve") ``` ## Save to figure -```{execute="false"} -using Cairo, Compose +```julia +using Compose # save to pdf draw(PDF("karate.pdf", 16cm, 16cm), gplot(g)) # save to png @@ -150,19 +150,34 @@ gplot(h) ``` # Arguments -+ `G` graph to plot -+ `layout` Optional. layout algorithm. Currently can choose from -[random_layout, circular_layout, spring_layout, stressmajorize_layout, -shell_layout, spectral_layout]. -Default: `spring_layout` -+ `nodelabel` Optional. Labels for the vertices. Default: `nothing` -+ `nodefillc` Optional. Color to fill the nodes with. -Default: `colorant"turquoise"` -+ `nodestrokec` Color for the node stroke. -Default: `nothing` -+ `arrowlengthfrac` Fraction of line length to use for arrows. -Set to 0 for no arrows. Default: 0 for undirected graph and 0.1 for directed graph -+ `arrowangleoffset` angular width in radians for the arrows. Default: `π/9` (20 degrees) ++ `G` Graph to draw ++ `locs_x, locs_y` Locations of the nodes (will be normalized and centered). If not specified, will be obtained from `layout` kwarg. + +# Keyword Arguments ++ `layout` Layout algorithm: `random_layout`, `circular_layout`, `spring_layout`, `shell_layout`, `stressmajorize_layout`, `spectral_layout`. Default: `spring_layout` ++ `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` ++ `nodelabelc` Color for the node labels, can be a Vector. Default: `colorant"black"` ++ `nodelabeldist` Distances for the node labels from center of nodes. Default: `0.0` ++ `nodelabelangleoffset` Angle offset for the node labels. Default: `π/4.0` ++ `NODELABELSIZE` Largest fontsize for the vertice labels. Default: `4.0` ++ `nodelabelsize` Relative fontsize for the vertice labels, can be a Vector. Default: `1.0` ++ `nodefillc` Color to fill the nodes with, can be a Vector. Default: `colorant"turquoise"` ++ `nodestrokec` Color for the nodes stroke, can be a Vector. Default: `nothing` ++ `nodestrokelw` Line width for the nodes stroke, can be a Vector. Default: `0.0` ++ `edgelabel` Labels for the edges, a Vector or nothing. Default: `[]` ++ `edgelabelc` Color for the edge labels, can be a Vector. Default: `colorant"black"` ++ `edgelabeldistx, edgelabeldisty` Distance for the edge label from center of edge. Default: `0.0` ++ `EDGELABELSIZE` Largest fontsize for the edge labels. Default: `4.0` ++ `edgelabelsize` Relative fontsize for the edge labels, can be a Vector. Default: `1.0` ++ `EDGELINEWIDTH` Max line width for the edges. Default: `0.25/sqrt(N)` ++ `edgelinewidth` Relative line width for the edges, can be a Vector. Default: `1.0` ++ `edgestrokec` Color for the edge strokes, can be a Vector. Default: `colorant"lightgray"` ++ `arrowlengthfrac` Fraction of line length to use for arrows. Equal to 0 for undirected graphs. Default: `0.1` for the directed graphs ++ `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)` # Reporting Bugs diff --git a/src/plot.jl b/src/plot.jl index b38554c..8c4c033 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -10,79 +10,89 @@ a Compose tree of the graph layout `G` Graph to draw +`locs_x, locs_y` +Locations of the nodes. Can be any units you want, +but will be normalized and centered anyway. If not provided, will +be obtained from `layout` kwarg. + +**Keyword Arguments** + `layout` -Optional. Layout algorithm. Currently can be one of [`random_layout`, +Layout algorithm. Currently can be one of [`random_layout`, `circular_layout`, `spring_layout`, `shell_layout`, `stressmajorize_layout`, `spectral_layout`]. Default: `spring_layout` -`locs_x, locs_y` -Locations of the nodes. Can be any units you want, -but will be normalized and centered anyway - `NODESIZE` -Optional. Max size for the nodes. Default: `3.0/sqrt(N)` +Max size for the nodes. Default: `3.0/sqrt(N)` `nodesize` -Optional. Relative size for the nodes, can be a Vector. Default: `1.0` +Relative size for the nodes, can be a Vector. Default: `1.0` `nodelabel` -Optional. Labels for the vertices, a Vector or nothing. Default: `nothing` +Labels for the vertices, a Vector or nothing. Default: `nothing` `nodelabelc` -Optional. Color for the node labels, can be a Vector. Default: `colorant"black"` +Color for the node labels, can be a Vector. Default: `colorant"black"` `nodelabeldist` -Optional. Distances for the node labels from center of nodes. Default: `0.0` +Distances for the node labels from center of nodes. Default: `0.0` `nodelabelangleoffset` -Optional. Angle offset for the node labels. Default: `π/4.0` +Angle offset for the node labels. Default: `π/4.0` `NODELABELSIZE` -Optional. Largest fontsize for the vertice labels. Default: `4.0` +Largest fontsize for the vertice labels. Default: `4.0` `nodelabelsize` -Optional. Relative fontsize for the vertice labels, can be a Vector. Default: `1.0` +Relative fontsize for the vertice labels, can be a Vector. Default: `1.0` `nodefillc` -Optional. Color to fill the nodes with, can be a Vector. Default: `colorant"turquoise"` +Color to fill the nodes with, can be a Vector. Default: `colorant"turquoise"` `nodestrokec` -Optional. Color for the nodes stroke, can be a Vector. Default: `nothing` +Color for the nodes stroke, can be a Vector. Default: `nothing` `nodestrokelw` -Optional. Line width for the nodes stroke, can be a Vector. Default: `0.0` +Line width for the nodes stroke, can be a Vector. Default: `0.0` `edgelabel` -Optional. Labels for the edges, a Vector or nothing. Default: `[]` +Labels for the edges, a Vector or nothing. Default: `[]` `edgelabelc` -Optional. Color for the edge labels, can be a Vector. Default: `colorant"black"` +Color for the edge labels, can be a Vector. Default: `colorant"black"` `edgelabeldistx, edgelabeldisty` -Optional. Distance for the edge label from center of edge. Default: `0.0` +Distance for the edge label from center of edge. Default: `0.0` `EDGELABELSIZE` -Optional. Largest fontsize for the edge labels. Default: `4.0` +Largest fontsize for the edge labels. Default: `4.0` `edgelabelsize` -Optional. Relative fontsize for the edge labels, can be a Vector. Default: `1.0` +Relative fontsize for the edge labels, can be a Vector. Default: `1.0` `EDGELINEWIDTH` -Optional. Max line width for the edges. Default: `0.25/sqrt(N)` +Max line width for the edges. Default: `0.25/sqrt(N)` `edgelinewidth` -Optional. Relative line width for the edges, can be a Vector. Default: `1.0` +Relative line width for the edges, can be a Vector. Default: `1.0` `edgestrokec` -Optional. Color for the edge strokes, can be a Vector. Default: `colorant"lightgray"` +Color for the edge strokes, can be a Vector. Default: `colorant"lightgray"` `arrowlengthfrac` -Optional. Fraction of line length to use for arrows. +Fraction of line length to use for arrows. Equal to 0 for undirected graphs. Default: `0.1` for the directed graphs `arrowangleoffset` -Optional. Angular width in radians for the arrows. Default: `π/9 (20 degrees)` +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)` """ function gplot(g::AbstractGraph{T}, @@ -108,9 +118,9 @@ function gplot(g::AbstractGraph{T}, nodestrokec = nothing, nodestrokelw = 0.0, arrowlengthfrac = is_directed(g) ? 0.1 : 0.0, - arrowangleoffset = π / 9.0, + arrowangleoffset = π / 9, linetype = "straight", - outangle = pi/5) where {T <:Integer, R <: Real} + outangle = π / 5) where {T <:Integer, R <: Real} length(locs_x_in) != length(locs_y_in) && error("Vectors must be same length") N = nv(g) From febb53bf5f587a7ec12a7bd4663564f27d21f4e4 Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Thu, 21 Jul 2022 17:44:03 -0500 Subject: [PATCH 02/18] fix #166 clarify that Cairo is required to visualize in vscode --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f5438ca..e385cee 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Other layout algorithms are wrapped from [NetworkX](https://github.com/networkx/ # Getting Started From the Julia REPL the latest version can be installed with -```{execute="false"} +```julia Pkg.add("GraphPlot") ``` GraphPlot is then loaded with @@ -132,6 +132,10 @@ gplot(g, locs_x, locs_y, nodelabel=nodelabel) gplot(g, linetype="curve") ``` +## Show plot + +When using an IDE such as VSCode, `Cairo.jl` is required to visualize the plot inside the IDE. + ## Save to figure ```julia using Compose From 9bffdd99d381ee4cec8c2b9702a9ed029a856d87 Mon Sep 17 00:00:00 2001 From: Hector Perez <hperez16@gmail.com> Date: Thu, 21 Jul 2022 18:02:52 -0500 Subject: [PATCH 03/18] Fix #175 to enable plotting to html Checking for System OS was outdated --- src/plot.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plot.jl b/src/plot.jl index 8c4c033..362ac90 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -241,11 +241,11 @@ end # take from [Gadfly.jl](https://github.com/dcjones/Gadfly.jl) function open_file(filename) - if Sys.KERNEL == :Darwin + if Sys.isapple(Sys.KERNEL) #apple run(`open $(filename)`) - elseif Sys.KERNEL == :Linux || Sys.KERNEL == :FreeBSD + elseif Sys.islinux(Sys.KERNEL) || Sys.isbsd(Sys.KERNEL) #linux run(`xdg-open $(filename)`) - elseif Sys.KERNEL == :Windows + elseif Sys.iswindows(Sys.KERNEL) #windows run(`$(ENV["COMSPEC"]) /c start $(filename)`) else @warn("Showing plots is not supported on OS $(string(Sys.KERNEL))") From 080a1a474edff73a4e9a034c8f90290045b0a20a Mon Sep 17 00:00:00 2001 From: Hector Perez <hperez16@gmail.com> Date: Thu, 21 Jul 2022 18:03:59 -0500 Subject: [PATCH 04/18] Document the use of gplothtml in README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e385cee..e5dd530 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,7 @@ gplot(g, linetype="curve") ## Show plot When using an IDE such as VSCode, `Cairo.jl` is required to visualize the plot inside the IDE. +When using the REPL, `gplothtml` will allow displaying the plot on a browser. ## Save to figure ```julia From 3d32d077c5d3bf73a497dddbca9700b4eca8c014 Mon Sep 17 00:00:00 2001 From: Hector Perez <hperez16@gmail.com> Date: Thu, 21 Jul 2022 18:08:05 -0500 Subject: [PATCH 05/18] Update open_file Now matches gadfly.jl (https://github.com/GiovineItalia/Gadfly.jl/blob/master/src/open_file.jl) --- src/plot.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plot.jl b/src/plot.jl index 362ac90..505f9b6 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -241,11 +241,11 @@ end # take from [Gadfly.jl](https://github.com/dcjones/Gadfly.jl) function open_file(filename) - if Sys.isapple(Sys.KERNEL) #apple + if Sys.isapple() #apple run(`open $(filename)`) - elseif Sys.islinux(Sys.KERNEL) || Sys.isbsd(Sys.KERNEL) #linux + elseif Sys.islinux() || Sys.isbsd() #linux run(`xdg-open $(filename)`) - elseif Sys.iswindows(Sys.KERNEL) #windows + elseif Sys.iswindows() #windows run(`$(ENV["COMSPEC"]) /c start $(filename)`) else @warn("Showing plots is not supported on OS $(string(Sys.KERNEL))") From 2c64095c0aee95cbb220224ab8022f1be0209e2f Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Mon, 25 Jul 2022 16:22:21 -0500 Subject: [PATCH 06/18] Minor changes: -allow gplothtml to accept same arguments as gplot -allow x/y-locs to be of different type (<: Real) --- src/plot.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plot.jl b/src/plot.jl index 505f9b6..af438b7 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -96,7 +96,7 @@ Default: `π/5 (36 degrees)` """ function gplot(g::AbstractGraph{T}, - locs_x_in::Vector{R}, locs_y_in::Vector{R}; + locs_x_in::Vector{R1}, locs_y_in::Vector{R2}; nodelabel = nothing, nodelabelc = colorant"black", nodelabelsize = 1.0, @@ -120,7 +120,7 @@ function gplot(g::AbstractGraph{T}, arrowlengthfrac = is_directed(g) ? 0.1 : 0.0, arrowangleoffset = π / 9, linetype = "straight", - outangle = π / 5) where {T <:Integer, R <: Real} + outangle = π / 5) where {T <:Integer, R1 <: Real, R2 <: Real} length(locs_x_in) != length(locs_y_in) && error("Vectors must be same length") N = nv(g) @@ -253,13 +253,13 @@ function open_file(filename) end # taken from [Gadfly.jl](https://github.com/dcjones/Gadfly.jl) -function gplothtml(g; layout::Function=spring_layout, keyargs...) +function gplothtml(args...; keyargs...) filename = string(tempname(), ".html") output = open(filename, "w") plot_output = IOBuffer() draw(SVGJS(plot_output, Compose.default_graphic_width, - Compose.default_graphic_width, false), gplot(g, layout(g)...; keyargs...)) + Compose.default_graphic_width, false), gplot(args...; keyargs...)) plotsvg = String(take!(plot_output)) write(output, From 222fb26a44cabc046779cf7d74bd5680ba7b2c65 Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Mon, 25 Jul 2022 23:26:46 -0500 Subject: [PATCH 07/18] add TagBot to repo --- .github/workflows/tagbot.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/tagbot.yml diff --git a/.github/workflows/tagbot.yml b/.github/workflows/tagbot.yml new file mode 100644 index 0000000..32a9dd8 --- /dev/null +++ b/.github/workflows/tagbot.yml @@ -0,0 +1,20 @@ +name: TagBot +on: + issue_comment: + types: + - created + workflow_dispatch: + inputs: + lookback: + default: 3 +permissions: + contents: write +jobs: + TagBot: + if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' + runs-on: ubuntu-latest + steps: + - uses: JuliaRegistries/TagBot@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + ssh: ${{ secrets.DOCUMENTER_KEY }} \ No newline at end of file From 14d62b4d3c829dbc0c3fdfd3ffd5897b0e48ee42 Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Tue, 26 Jul 2022 11:59:01 -0500 Subject: [PATCH 08/18] Fix #172. set background color (`backgroundc` kwarg): and minor changes to plots.jl update README --- README.md | 1 + src/plot.jl | 30 +++++++++++++++++------------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e5dd530..0ea4643 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,7 @@ 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)` ++ `backgroundc` Color for the plot background. Default: `nothing` # Reporting Bugs diff --git a/src/plot.jl b/src/plot.jl index af438b7..58b0bc6 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -42,10 +42,10 @@ Distances for the node labels from center of nodes. Default: `0.0` Angle offset for the node labels. Default: `π/4.0` `NODELABELSIZE` -Largest fontsize for the vertice labels. Default: `4.0` +Largest fontsize for the vertex labels. Default: `4.0` `nodelabelsize` -Relative fontsize for the vertice labels, can be a Vector. Default: `1.0` +Relative fontsize for the vertex labels, can be a Vector. Default: `1.0` `nodefillc` Color to fill the nodes with, can be a Vector. Default: `colorant"turquoise"` @@ -94,6 +94,9 @@ 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)` +`backgroundc` +Color for the plot background. Default: `nothing` + """ function gplot(g::AbstractGraph{T}, locs_x_in::Vector{R1}, locs_y_in::Vector{R2}; @@ -120,7 +123,8 @@ 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, + backgroundc = nothing) where {T <:Integer, R1 <: Real, R2 <: Real} length(locs_x_in) != length(locs_y_in) && error("Vectors must be same length") N = nv(g) @@ -169,19 +173,19 @@ function gplot(g::AbstractGraph{T}, # Create nodes nodecircle = fill(0.4Compose.w, length(locs_x)) if isa(nodesize, Real) - for i = 1:length(locs_x) - nodecircle[i] *= nodesize - end - else - for i = 1:length(locs_x) - nodecircle[i] *= nodesize[i] - end - end + for i = 1:length(locs_x) + nodecircle[i] *= nodesize + end + else + for i = 1:length(locs_x) + nodecircle[i] *= nodesize[i] + end + end nodes = circle(locs_x, locs_y, nodecircle) # Create node labels if provided texts = nothing - if nodelabel != nothing + if !isnothing(nodelabel) text_locs_x = deepcopy(locs_x) text_locs_y = deepcopy(locs_y) texts = text(text_locs_x .+ nodesize .* (nodelabeldist * cos(nodelabelangleoffset)), @@ -227,7 +231,7 @@ function gplot(g::AbstractGraph{T}, end end - compose(context(units=UnitBox(-1.2, -1.2, +2.4, +2.4)), + compose(context(units=UnitBox(-1.2, -1.2, +2.4, +2.4)), rectangle(-1.2, -1.2, +2.4, +2.4), fill(backgroundc), compose(context(), texts, fill(nodelabelc), stroke(nothing), fontsize(nodelabelsize)), compose(context(), nodes, fill(nodefillc), stroke(nodestrokec), linewidth(nodestrokelw)), compose(context(), edgetexts, fill(edgelabelc), stroke(nothing), fontsize(edgelabelsize)), From d610f151efbf4613591e2ca8c85fbd9d853d0bdd Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Tue, 26 Jul 2022 20:28:16 -0500 Subject: [PATCH 09/18] update arg syntax for gplot: (address #177) -breaking change: linetype changed from String to Symbol -breaking change: default for edgelabel is nothing (not []) to make consistent with nodelabel default -remove all caps args -improve some of the code in gplot (use isnothing, etc.) --- README.md | 14 ++++----- src/plot.jl | 76 +++++++++++++++++------------------------------- test/runtests.jl | 4 +-- 3 files changed, 35 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 0ea4643..49c5313 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ gplot(g, locs_x, locs_y, nodelabel=nodelabel) ## Curve edge ```julia -gplot(g, linetype="curve") +gplot(g, linetype=:curve) ``` ## Show plot @@ -160,28 +160,28 @@ gplot(h) # Keyword Arguments + `layout` Layout algorithm: `random_layout`, `circular_layout`, `spring_layout`, `shell_layout`, `stressmajorize_layout`, `spectral_layout`. Default: `spring_layout` -+ `NODESIZE` Max size for the nodes. Default: `3.0/sqrt(N)` ++ `max_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` + `nodelabelc` Color for the node labels, can be a Vector. Default: `colorant"black"` + `nodelabeldist` Distances for the node labels from center of nodes. Default: `0.0` + `nodelabelangleoffset` Angle offset for the node labels. Default: `π/4.0` -+ `NODELABELSIZE` Largest fontsize for the vertice labels. Default: `4.0` ++ `max_nodelabelsize` Largest fontsize for the vertice labels. Default: `4.0` + `nodelabelsize` Relative fontsize for the vertice labels, can be a Vector. Default: `1.0` + `nodefillc` Color to fill the nodes with, can be a Vector. Default: `colorant"turquoise"` + `nodestrokec` Color for the nodes stroke, can be a Vector. Default: `nothing` + `nodestrokelw` Line width for the nodes stroke, can be a Vector. Default: `0.0` -+ `edgelabel` Labels for the edges, a Vector or nothing. Default: `[]` ++ `edgelabel` Labels for the edges, a Vector or nothing. Default: `nothing` + `edgelabelc` Color for the edge labels, can be a Vector. Default: `colorant"black"` + `edgelabeldistx, edgelabeldisty` Distance for the edge label from center of edge. Default: `0.0` -+ `EDGELABELSIZE` Largest fontsize for the edge labels. Default: `4.0` ++ `max_edgelabelsize` Largest fontsize for the edge labels. Default: `4.0` + `edgelabelsize` Relative fontsize for the edge labels, can be a Vector. Default: `1.0` -+ `EDGELINEWIDTH` Max line width for the edges. Default: `0.25/sqrt(N)` ++ `max_edgelinewidth` Max line width for the edges. Default: `0.25/sqrt(N)` + `edgelinewidth` Relative line width for the edges, can be a Vector. Default: `1.0` + `edgestrokec` Color for the edge strokes, can be a Vector. Default: `colorant"lightgray"` + `arrowlengthfrac` Fraction of line length to use for arrows. Equal to 0 for undirected graphs. Default: `0.1` for the directed graphs + `arrowangleoffset` Angular width in radians for the arrows. Default: `π/9 (20 degrees)` -+ `linetype` Type of line used for edges ("straight", "curve"). Default: "straight" ++ `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)` + `backgroundc` Color for the plot background. Default: `nothing` diff --git a/src/plot.jl b/src/plot.jl index 58b0bc6..72c04bb 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -23,7 +23,7 @@ Layout algorithm. Currently can be one of [`random_layout`, `spectral_layout`]. Default: `spring_layout` -`NODESIZE` +`max_nodesize` Max size for the nodes. Default: `3.0/sqrt(N)` `nodesize` @@ -41,7 +41,7 @@ Distances for the node labels from center of nodes. Default: `0.0` `nodelabelangleoffset` Angle offset for the node labels. Default: `π/4.0` -`NODELABELSIZE` +`max_nodelabelsize` Largest fontsize for the vertex labels. Default: `4.0` `nodelabelsize` @@ -57,7 +57,7 @@ Color for the nodes stroke, can be a Vector. Default: `nothing` Line width for the nodes stroke, can be a Vector. Default: `0.0` `edgelabel` -Labels for the edges, a Vector or nothing. Default: `[]` +Labels for the edges, a Vector or nothing. Default: `nothing` `edgelabelc` Color for the edge labels, can be a Vector. Default: `colorant"black"` @@ -65,13 +65,13 @@ Color for the edge labels, can be a Vector. Default: `colorant"black"` `edgelabeldistx, edgelabeldisty` Distance for the edge label from center of edge. Default: `0.0` -`EDGELABELSIZE` +`max_edgelabelsize` Largest fontsize for the edge labels. Default: `4.0` `edgelabelsize` Relative fontsize for the edge labels, can be a Vector. Default: `1.0` -`EDGELINEWIDTH` +`max_edgelinewidth` Max line width for the edges. Default: `0.25/sqrt(N)` `edgelinewidth` @@ -88,7 +88,7 @@ Equal to 0 for undirected graphs. Default: `0.1` for the directed graphs Angular width in radians for the arrows. Default: `π/9 (20 degrees)` `linetype` -Type of line used for edges ("straight", "curve"). Default: "straight" +Type of line used for edges (:straight, :curve). Default: :straight `outangle` Angular width in radians for the edges (only used if `linetype = "curve`). @@ -103,38 +103,32 @@ function gplot(g::AbstractGraph{T}, nodelabel = nothing, nodelabelc = colorant"black", nodelabelsize = 1.0, - NODELABELSIZE = 4.0, + max_nodelabelsize = 4.0, nodelabeldist = 0.0, nodelabelangleoffset = π / 4.0, - edgelabel = [], + edgelabel = nothing, edgelabelc = colorant"black", edgelabelsize = 1.0, - EDGELABELSIZE = 4.0, + max_edgelabelsize = 4.0, edgestrokec = colorant"lightgray", edgelinewidth = 1.0, - EDGELINEWIDTH = 3.0 / sqrt(nv(g)), + max_edgelinewidth = 3.0 / sqrt(nv(g)), edgelabeldistx = 0.0, edgelabeldisty = 0.0, nodesize = 1.0, - NODESIZE = 0.25 / sqrt(nv(g)), + max_nodesize = 0.25 / sqrt(nv(g)), nodefillc = colorant"turquoise", nodestrokec = nothing, nodestrokelw = 0.0, arrowlengthfrac = is_directed(g) ? 0.1 : 0.0, arrowangleoffset = π / 9, - linetype = "straight", + linetype = :straight, outangle = π / 5, backgroundc = nothing) where {T <:Integer, R1 <: Real, R2 <: Real} - length(locs_x_in) != length(locs_y_in) && error("Vectors must be same length") - N = nv(g) - NE = ne(g) - if nodelabel != nothing && length(nodelabel) != N - error("Must have one label per node (or none)") - end - if !isempty(edgelabel) && length(edgelabel) != NE - error("Must have one label per edge (or none)") - end + @assert length(locs_x_in) == length(locs_y_in) == nv(g) "Position vectors must be of the same length as the number of nodes" + @assert isnothing(nodelabel) || length(nodelabel) == nv(g) "`nodelabel` must either be `nothing` or a vector of the same length as the number of nodes" + @assert isnothing(edgelabel) || length(edgelabel) == ne(g) "`edgelabel` must either be `nothing` or a vector of the same length as the number of edges" locs_x = Float64.(locs_x_in) locs_y = Float64.(locs_y_in) @@ -152,35 +146,18 @@ function gplot(g::AbstractGraph{T}, map!(z -> scaler(z, min_x, max_x), locs_x, locs_x) map!(z -> scaler(z, min_y, max_y), locs_y, locs_y) - # Determine sizes - #NODESIZE = 0.25/sqrt(N) - #LINEWIDTH = 3.0/sqrt(N) - - max_nodesize = NODESIZE / maximum(nodesize) - nodesize *= max_nodesize - max_edgelinewidth = EDGELINEWIDTH / maximum(edgelinewidth) - edgelinewidth *= max_edgelinewidth - max_edgelabelsize = EDGELABELSIZE / maximum(edgelabelsize) - edgelabelsize *= max_edgelabelsize - max_nodelabelsize = NODELABELSIZE / maximum(nodelabelsize) - nodelabelsize *= max_nodelabelsize + # Scale sizes + nodesize *= (max_nodesize / maximum(nodesize)) + edgelinewidth *= (max_edgelinewidth / maximum(edgelinewidth)) + edgelabelsize *= (max_edgelabelsize / maximum(edgelabelsize)) + nodelabelsize *= (max_nodelabelsize / maximum(nodelabelsize)) max_nodestrokelw = maximum(nodestrokelw) if max_nodestrokelw > 0.0 - max_nodestrokelw = EDGELINEWIDTH / max_nodestrokelw - nodestrokelw *= max_nodestrokelw + nodestrokelw *= (max_edgelinewidth / max_nodestrokelw) end # Create nodes - nodecircle = fill(0.4Compose.w, length(locs_x)) - if isa(nodesize, Real) - for i = 1:length(locs_x) - nodecircle[i] *= nodesize - end - else - for i = 1:length(locs_x) - nodecircle[i] *= nodesize[i] - end - end + nodecircle = fill(0.4Compose.w, nv(g)) .* nodesize nodes = circle(locs_x, locs_y, nodecircle) # Create node labels if provided @@ -194,7 +171,7 @@ function gplot(g::AbstractGraph{T}, end # Create edge labels if provided edgetexts = nothing - if !isempty(edgelabel) + if !isnothing(edgelabel) edge_locs_x = zeros(R, NE) edge_locs_y = zeros(R, NE) for (e_idx, e) in enumerate(edges(g)) @@ -202,16 +179,15 @@ function gplot(g::AbstractGraph{T}, j = dst(e) mid_x = (locs_x[i]+locs_x[j]) / 2.0 mid_y = (locs_y[i]+locs_y[j]) / 2.0 - edge_locs_x[e_idx] = (is_directed(g) ? (mid_x+locs_x[j]) / 2.0 : mid_x) + edgelabeldistx * NODESIZE - edge_locs_y[e_idx] = (is_directed(g) ? (mid_y+locs_y[j]) / 2.0 : mid_y) + edgelabeldisty * NODESIZE - + edge_locs_x[e_idx] = (is_directed(g) ? (mid_x+locs_x[j]) / 2.0 : mid_x) + edgelabeldistx * max_nodesize + edge_locs_y[e_idx] = (is_directed(g) ? (mid_y+locs_y[j]) / 2.0 : mid_y) + edgelabeldisty * max_nodesize end edgetexts = text(edge_locs_x, edge_locs_y, map(string, edgelabel), [hcenter], [vcenter]) end # Create lines and arrow heads lines, arrows = nothing, nothing - if linetype == "curve" + 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]) diff --git a/test/runtests.jl b/test/runtests.jl index f38f8d6..4014ed5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -93,7 +93,7 @@ end add_edge!(g2, 1,2) add_edge!(g2, 2,1) - plot_and_save1(fname) = plot_and_save(fname, g2, linetype="curve") + plot_and_save1(fname) = plot_and_save(fname, g2, linetype=:curve) refimg1 = joinpath(datadir, "curve.png") @test test_images(VisualTest(plot_and_save1, refimg1), popup=!istravis) |> save_comparison |> success @@ -102,7 +102,7 @@ end add_edge!(g3, 1,2) add_edge!(g3, 2,1) - plot_and_save2(fname) = plot_and_save(fname, g3, linetype="curve") + plot_and_save2(fname) = plot_and_save(fname, g3, linetype=:curve) refimg2 = joinpath(datadir, "self_directed.png") @test test_images(VisualTest(plot_and_save2, refimg2), popup=!istravis) |> save_comparison |> success From 5bc0ba37deb92dc0a10a1eca37946577c01a437d Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Wed, 27 Jul 2022 00:32:11 -0500 Subject: [PATCH 10/18] clarify docstring fix background color --- README.md | 2 +- src/plot.jl | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 49c5313..58ada52 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,7 @@ gplot(h) + `nodelabel` Labels for the vertices, a Vector or nothing. Default: `nothing` + `nodelabelc` Color for the node labels, can be a Vector. Default: `colorant"black"` + `nodelabeldist` Distances for the node labels from center of nodes. Default: `0.0` -+ `nodelabelangleoffset` Angle offset for the node labels. Default: `π/4.0` ++ `nodelabelangleoffset` Angle offset for the node labels (only used when `nodelabeldist` is not zero). Default: `π/4.0` + `max_nodelabelsize` Largest fontsize for the vertice labels. Default: `4.0` + `nodelabelsize` Relative fontsize for the vertice labels, can be a Vector. Default: `1.0` + `nodefillc` Color to fill the nodes with, can be a Vector. Default: `colorant"turquoise"` diff --git a/src/plot.jl b/src/plot.jl index 72c04bb..d8e6248 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -39,7 +39,7 @@ Color for the node labels, can be a Vector. Default: `colorant"black"` Distances for the node labels from center of nodes. Default: `0.0` `nodelabelangleoffset` -Angle offset for the node labels. Default: `π/4.0` +Angle offset for the node labels (only used when `nodelabeldist` is not zero). Default: `π/4.0` `max_nodelabelsize` Largest fontsize for the vertex labels. Default: `4.0` @@ -188,7 +188,7 @@ function gplot(g::AbstractGraph{T}, # Create lines and arrow heads lines, arrows = nothing, nothing if linetype == :curve - if arrowlengthfrac > 0.0 + if !iszero(arrowlengthfrac) 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) @@ -197,7 +197,7 @@ function gplot(g::AbstractGraph{T}, lines = curve(curves_cord[:,1], curves_cord[:,2], curves_cord[:,3], curves_cord[:,4]) end else - if arrowlengthfrac > 0.0 + if !iszero(arrowlengthfrac) lines_cord, arrows_cord = graphline(g, locs_x, locs_y, nodesize, arrowlengthfrac, arrowangleoffset) lines = line(lines_cord) arrows = line(arrows_cord) @@ -207,7 +207,8 @@ function gplot(g::AbstractGraph{T}, end end - compose(context(units=UnitBox(-1.2, -1.2, +2.4, +2.4)), rectangle(-1.2, -1.2, +2.4, +2.4), fill(backgroundc), + compose(context(units=UnitBox(-1.2, -1.2, +2.4, +2.4)), + compose(context(), rectangle(-1.2, -1.2, +2.4, +2.4), fill(backgroundc)), compose(context(), texts, fill(nodelabelc), stroke(nothing), fontsize(nodelabelsize)), compose(context(), nodes, fill(nodefillc), stroke(nodestrokec), linewidth(nodestrokelw)), compose(context(), edgetexts, fill(edgelabelc), stroke(nothing), fontsize(edgelabelsize)), From ef373d5b4ddfa83bb751f12ba1dd9939aa7611df Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Wed, 27 Jul 2022 01:52:30 -0500 Subject: [PATCH 11/18] minor changes: -use `iszero` -remove `stroke(nothing)` or `fill(nothing` as `nothing` is already the default for these functions in Compose.jl --- src/plot.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plot.jl b/src/plot.jl index d8e6248..1df938b 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -152,7 +152,7 @@ function gplot(g::AbstractGraph{T}, edgelabelsize *= (max_edgelabelsize / maximum(edgelabelsize)) nodelabelsize *= (max_nodelabelsize / maximum(nodelabelsize)) max_nodestrokelw = maximum(nodestrokelw) - if max_nodestrokelw > 0.0 + if !iszero(max_nodestrokelw) nodestrokelw *= (max_edgelinewidth / max_nodestrokelw) end @@ -207,13 +207,14 @@ function gplot(g::AbstractGraph{T}, end end + #build plot compose(context(units=UnitBox(-1.2, -1.2, +2.4, +2.4)), compose(context(), rectangle(-1.2, -1.2, +2.4, +2.4), fill(backgroundc)), - compose(context(), texts, fill(nodelabelc), stroke(nothing), fontsize(nodelabelsize)), + compose(context(), texts, fill(nodelabelc), fontsize(nodelabelsize)), compose(context(), nodes, fill(nodefillc), stroke(nodestrokec), linewidth(nodestrokelw)), - compose(context(), edgetexts, fill(edgelabelc), stroke(nothing), fontsize(edgelabelsize)), + compose(context(), edgetexts, fill(edgelabelc), fontsize(edgelabelsize)), compose(context(), arrows, stroke(edgestrokec), linewidth(edgelinewidth)), - compose(context(), lines, stroke(edgestrokec), fill(nothing), linewidth(edgelinewidth))) + compose(context(), lines, stroke(edgestrokec), linewidth(edgelinewidth))) end function gplot(g; layout::Function=spring_layout, keyargs...) From 4d574e0d95d838dc2c78275396043ee7157a304d Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Wed, 27 Jul 2022 09:16:46 -0500 Subject: [PATCH 12/18] clean up repo: -move layouts to layouts.jl -add community_layout to readme -remove deprecations -remove shape.jl and pienode.jl (not used anywhere) --- README.md | 15 ++- src/GraphPlot.jl | 5 - src/collapse_plot.jl | 96 --------------- src/deprecations.jl | 106 ---------------- src/layout.jl | 287 ++++++++++++++++++++++++++++++++++++++++++- src/pienode.jl | 41 ------- src/plot.jl | 2 +- src/shape.jl | 9 -- src/stress.jl | 175 -------------------------- 9 files changed, 301 insertions(+), 435 deletions(-) delete mode 100644 src/collapse_plot.jl delete mode 100644 src/deprecations.jl delete mode 100644 src/pienode.jl delete mode 100644 src/shape.jl delete mode 100644 src/stress.jl diff --git a/README.md b/README.md index 58ada52..f012ea5 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,19 @@ locs_x, locs_y = shell_layout(g, nlist) gplot(g, locs_x, locs_y, nodelabel=nodelabel) ``` +### stress majorize layout +```julia +gplot(g, layout=stressmajorize_layout) +``` + +### community layout +```julia +community_id = rand(1:3, nv(g)) #membership for each node +node_c = [colorant"red",colorant"yellow",colorant"blue"] #colors for each community +locs_x, locs_y = community_layout(g,community_id) +gplot(g, locs_x, locs_y, nodefillc = node_c[community_id]) +``` + ## Curve edge ```julia gplot(g, linetype=:curve) @@ -159,7 +172,7 @@ gplot(h) + `locs_x, locs_y` Locations of the nodes (will be normalized and centered). If not specified, will be obtained from `layout` kwarg. # Keyword Arguments -+ `layout` Layout algorithm: `random_layout`, `circular_layout`, `spring_layout`, `shell_layout`, `stressmajorize_layout`, `spectral_layout`. Default: `spring_layout` ++ `layout` Layout algorithm: `random_layout`, `circular_layout`, `spring_layout`, `shell_layout`, `stressmajorize_layout`, `spectral_layout`, `community_layout`. Default: `spring_layout` + `max_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` diff --git a/src/GraphPlot.jl b/src/GraphPlot.jl index c1738c1..3472fb8 100644 --- a/src/GraphPlot.jl +++ b/src/GraphPlot.jl @@ -17,16 +17,11 @@ export shell_layout, stressmajorize_layout -include("deprecations.jl") - # layout algorithms include("layout.jl") -include("stress.jl") # ploting utilities -include("shape.jl") include("lines.jl") include("plot.jl") -include("collapse_plot.jl") end # module diff --git a/src/collapse_plot.jl b/src/collapse_plot.jl deleted file mode 100644 index 2e1e062..0000000 --- a/src/collapse_plot.jl +++ /dev/null @@ -1,96 +0,0 @@ -using GraphPlot - -function collapse_graph(g::AbstractGraph, membership::Vector{Int}) - nb_comm = maximum(membership) - - collapsed_edge_weights = Vector{Dict{Int,Float64}}(undef, nb_comm) - for i=1:nb_comm - collapsed_edge_weights[i] = Dict{Int,Float64}() - end - - for e in edges(g) - u = src(e) - v = dst(e) - u_comm = membership[u] - v_comm = membership[v] - - # for special case of undirected network - if !is_directed(g) - u_comm, v_comm = minmax(u_comm, v_comm) - end - - if haskey(collapsed_edge_weights[u_comm], v_comm) - collapsed_edge_weights[u_comm][v_comm] += 1 - else - collapsed_edge_weights[u_comm][v_comm] = 1 - end - end - - collapsed_graph = SimpleGraph(nb_comm) - collapsed_weights = Float64[] - - for u=1:nb_comm - for (v,w) in collapsed_edge_weights[u] - add_edge!(collapsed_graph, u, v) - push!(collapsed_weights, w) - end - end - - return collapsed_graph, collapsed_weights -end - -function community_layout(g::AbstractGraph, membership::Vector{Int}) - N = length(membership) - lx = zeros(N) - ly = zeros(N) - comms = Dict{Int,Vector{Int}}() - for (idx,lbl) in enumerate(membership) - if haskey(comms, lbl) - push!(comms[lbl], idx) - else - comms[lbl] = Int[idx] - end - end - h, w = collapse_graph(g, membership) - clx, cly = spring_layout(h) - for (lbl, nodes) in comms - θ = range(0, stop=2pi, length=(length(nodes) + 1))[1:end-1] - for (idx, node) in enumerate(nodes) - lx[node] = 1.8*length(nodes)/N*cos(θ[idx]) + clx[lbl] - ly[node] = 1.8*length(nodes)/N*sin(θ[idx]) + cly[lbl] - end - end - return lx, ly -end - -function collapse_layout(g::AbstractGraph, membership::Vector{Int}) - sg = Graphs.SimpleGraph(nv(g)) - for e in edges(g) - u = src(e) - v = dst(e) - Graphs.add_edge!(sg, u, v) - end - N = length(membership) - lx = zeros(N) - ly = zeros(N) - comms = Dict{Int,Vector{Int}}() - for (idx,lbl) in enumerate(membership) - if haskey(comms, lbl) - push!(comms[lbl], idx) - else - comms[lbl] = Int[idx] - end - end - h, w = collapse_graph(g, membership) - clx, cly = spring_layout(h) - for (lbl, nodes) in comms - subg = sg[nodes] - sublx, subly = spring_layout(subg) - θ = range(0, stop=2pi, length=(length(nodes) + 1))[1:end-1] - for (idx, node) in enumerate(nodes) - lx[node] = 1.8*length(nodes)/N*sublx[idx] + clx[lbl] - ly[node] = 1.8*length(nodes)/N*subly[idx] + cly[lbl] - end - end - return lx, ly -end diff --git a/src/deprecations.jl b/src/deprecations.jl deleted file mode 100644 index 4e07ac3..0000000 --- a/src/deprecations.jl +++ /dev/null @@ -1,106 +0,0 @@ -using Base: depwarn - - -function _nv(g) - depwarn("`GraphPlot._nv(g)` is deprectated. Use `Graphs.nv(g)` instead.", :_nv) - return Graphs.nv(g) -end - -function _ne(g) - depwarn("`GraphPlot._ne(g)` is deprectated. Use `Graphs.ne(g)` instead.", :_ne) - return Graphs.ne(g) -end - -function _vertices(g) - depwarn("`GraphPlot._vertices(g)` is deprectated. Use `Graphs.vertices(g)` instead.", :_vertices) - return Graphs.vertices(g) -end - -function _edges(g) - depwarn("`GraphPlot._edges(g)` is deprectated. Use `Graphs.edges(g)` instead.", :_edges) - return Graphs.edges(g) -end - -function _src_index(e, g) - depwarn("`GraphPlot._src_index(g)` is deprectated. Use `Graphs.src(e)` instead.", :_src_index) - return Graphs.src(e) -end - -function _dst_index(e, g) - depwarn("`GraphPlot._dst_index(g)` is deprectated. Use `Graphs.dst(e)` instead.", :_dst_index) - return Graphs.dst(e) -end - -function _adjacency_matrix(g) - depwarn("`GraphPlot._adjacency_matrix(g)` is deprectated. Use `Graphs.adjacency_matrix(g)` instead.", :_adjacency_matrix) - return Graphs.adjacency_matrix(g) -end - -function _is_directed(g) - depwarn("`GraphPlot._is_directed(g)` is deprectated. Use `Graphs.is_directed(g)` instead.", :_is_directed) - return Graphs.is_directed(g) -end - -function _laplacian_matrix(g) - depwarn("`GraphPlot._laplacian_matrix(g)` is deprectated. Use `Graphs.laplacian_matrix(g)` instead.", :_laplacian_matrix) - return Graphs.laplacian_matrix(g) -end - - -""" -read some famous graphs - -**Paramenters** - -*graphname* -Currently, `graphname` can be one of ["karate", "football", "dolphins", -"netscience", "polbooks", "power", "cond-mat"] - -**Return** -a graph - -**Example** - julia> g = graphfamous("karate") -""" -function graphfamous(graphname::AbstractString) - depwarn(""" - `graphfamous` has been deprecated and will be removed in the future. Consider the package `GraphIO.jl` for loading graphs. - """, :graphfamous) - file = joinpath(dirname(@__DIR__), "data", graphname*".dat") - readedgelist(file) -end -export graphfamous - -using DelimitedFiles: readdlm -"""read graph from in edgelist format""" -function readedgelist(filename; is_directed::Bool=false, start_index::Int=0, delim::Char=' ') - depwarn(""" - `graphfamous` has been deprecated and will be removed in the future. Consider the package `GraphIO.jl` for loading graphs. - """, :graphfamous) - es = readdlm(filename, delim, Int) - es = unique(es, dims=1) - if start_index == 0 - es = es .+ 1 - end - N = maximum(es) - if is_directed - g = DiGraph(N) - for i=1:size(es,1) - add_edge!(g, es[i,1], es[i,2]) - end - return g - else - for i=1:size(es,1) - if es[i,1] > es[i,2] - es[i,1], es[i,2] = es[i,2], es[i,1] - end - end - es = unique(es, dims=1) - g = Graph(N) - for i=1:size(es,1) - add_edge!(g, es[i,1], es[i,2]) - end - return g - end -end -export readedgelist diff --git a/src/layout.jl b/src/layout.jl index 2a9956b..5507b89 100644 --- a/src/layout.jl +++ b/src/layout.jl @@ -1,7 +1,7 @@ using SparseArrays: SparseMatrixCSC, sparse using ArnoldiMethod: SR using Base: OneTo -using LinearAlgebra: eigen +using LinearAlgebra: eigen, norm """ Position nodes uniformly at random in the unit square. @@ -284,3 +284,288 @@ function _spectral(A::SparseMatrixCSC) index = sortperm(real(eigenvalues))[2:3] return real(eigenvectors[:, index[1]]), real(eigenvectors[:, index[2]]) end + +# This layout algorithm is copy from [IainNZ](https://github.com/IainNZ)'s [GraphLayout.jl](https://github.com/IainNZ/GraphLayout.jl) +@doc """ +Compute graph layout using stress majorization + +Inputs: + + δ: Matrix of pairwise distances + p: Dimension of embedding (default: 2) + w: Matrix of weights. If not specified, defaults to + w[i,j] = δ[i,j]^-2 if δ[i,j] is nonzero, or 0 otherwise + X0: Initial guess for the layout. Coordinates are given in rows. + If not specified, default to random matrix of Gaussians + +Additional optional keyword arguments control the convergence of the algorithm +and the additional output as requested: + + maxiter: Maximum number of iterations. Default: 400size(X0, 1)^2 + abstols: Absolute tolerance for convergence of stress. + The iterations terminate if the difference between two + successive stresses is less than abstol. + Default: √(eps(eltype(X0)) + reltols: Relative tolerance for convergence of stress. + The iterations terminate if the difference between two + successive stresses relative to the current stress is less than + reltol. Default: √(eps(eltype(X0)) + abstolx: Absolute tolerance for convergence of layout. + The iterations terminate if the Frobenius norm of two successive + layouts is less than abstolx. Default: √(eps(eltype(X0)) + verbose: If true, prints convergence information at each iteration. + Default: false + returnall: If true, returns all iterates and their associated stresses. + If false (default), returns the last iterate + +Output: + + The final layout X, with coordinates given in rows, unless returnall=true. + +Reference: + + The main equation to solve is (8) of: + + @incollection{ + author = {Emden R Gansner and Yehuda Koren and Stephen North}, + title = {Graph Drawing by Stress Majorization} + year={2005}, + isbn={978-3-540-24528-5}, + booktitle={Graph Drawing}, + seriesvolume={3383}, + series={Lecture Notes in Computer Science}, + editor={Pach, J\'anos}, + doi={10.1007/978-3-540-31843-9_25}, + publisher={Springer Berlin Heidelberg}, + pages={239--250}, + } +""" +function stressmajorize_layout(g::AbstractGraph, + p::Int=2, + w=nothing, + X0=randn(nv(g), p); + maxiter = 400size(X0, 1)^2, + abstols=√(eps(eltype(X0))), + reltols=√(eps(eltype(X0))), + abstolx=√(eps(eltype(X0))), + verbose = false) + + @assert size(X0, 2)==p + δ = fill(1.0, nv(g), nv(g)) + + if w == nothing + w = δ.^-2 + w[.!isfinite.(w)] .= 0 + end + + @assert size(X0, 1)==size(δ, 1)==size(δ, 2)==size(w, 1)==size(w, 2) + Lw = weightedlaplacian(w) + pinvLw = pinv(Lw) + newstress = stress(X0, δ, w) + Xs = Matrix[X0] + stresses = [newstress] + iter = 0 + for outer iter = 1:maxiter + #TODO the faster way is to drop the first row and col from the iteration + X = pinvLw * (LZ(X0, δ, w)*X0) + @assert all(isfinite.(X)) + newstress, oldstress = stress(X, δ, w), newstress + verbose && @info("""Iteration $iter + Change in coordinates: $(norm(X - X0)) + Stress: $newstress (change: $(newstress-oldstress)) + """) + push!(Xs, X) + push!(stresses, newstress) + abs(newstress - oldstress) < reltols * newstress && break + abs(newstress - oldstress) < abstols && break + norm(X - X0) < abstolx && break + X0 = X + end + iter == maxiter && @warn("Maximum number of iterations reached without convergence") + + Xs[end][:,1], Xs[end][:,2] +end + +@doc """ +Stress function to majorize + +Input: + X: A particular layout (coordinates in rows) + d: Matrix of pairwise distances + w: Weights for each pairwise distance + +See (1) of Reference +""" +function stress(X, d=fill(1.0, size(X, 1), size(X, 1)), w=nothing) + s = 0.0 + n = size(X, 1) + if w==nothing + w = d.^-2 + w[!isfinite.(w)] = 0 + end + @assert n==size(d, 1)==size(d, 2)==size(w, 1)==size(w, 2) + for j=1:n, i=1:j-1 + s += w[i, j] * (norm(X[i,:] - X[j,:]) - d[i,j])^2 + end + @assert isfinite(s) + return s +end + +@doc """ +Compute weighted Laplacian given ideal weights w + +Lʷ defined in (4) of the Reference +""" +function weightedlaplacian(w) + n = LinearAlgebra.checksquare(w) + T = eltype(w) + Lw = zeros(T, n, n) + for i=1:n + D = zero(T) + for j=1:n + i==j && continue + Lw[i, j] = -w[i, j] + D += w[i, j] + end + Lw[i, i] = D + end + return Lw +end + +@doc """ +Computes L^Z defined in (5) of the Reference + +Input: Z: current layout (coordinates) + d: Ideal distances (default: all 1) + w: weights (default: d.^-2) +""" +function LZ(Z, d, w) + n = size(Z, 1) + L = zeros(n, n) + for i=1:n + D = 0.0 + for j=1:n + i==j && continue + nrmz = norm(Z[i,:] - Z[j,:]) + nrmz==0 && continue + δ = w[i, j] * d[i, j] + L[i, j] = -δ/nrmz + D -= -δ/nrmz + end + L[i, i] = D + end + @assert all(isfinite.(L)) + L +end + +""" +Community layout for graphs with pre-defined community assignments + +**Parameters** + +*g* +a graph + +*membership* +`Vector` indicating the membership (`Int`) of each node + +**Examples** +``` +julia> g = smallgraph(:karate) +julia> member_id = rand(1:5, nv(g)) +julia> locs_x, locs_y = spectral_layout(g, member_id) +``` +""" +function community_layout(g::AbstractGraph, membership::Vector{Int}=collect(vertices(g))) + N = length(membership) + lx = zeros(N) + ly = zeros(N) + comms = Dict{Int,Vector{Int}}() + for (idx,lbl) in enumerate(membership) + if haskey(comms, lbl) + push!(comms[lbl], idx) + else + comms[lbl] = Int[idx] + end + end + h = collapse_graph(g, membership)[1] + clx, cly = spring_layout(h) + for (lbl, nodes) in comms + θ = range(0, stop=2pi, length=(length(nodes) + 1))[1:end-1] + for (idx, node) in enumerate(nodes) + lx[node] = 1.8*length(nodes)/N*cos(θ[idx]) + clx[lbl] + ly[node] = 1.8*length(nodes)/N*sin(θ[idx]) + cly[lbl] + end + end + return lx, ly +end + +function collapse_layout(g::AbstractGraph, membership::Vector{Int}) + sg = Graphs.SimpleGraph(nv(g)) + for e in edges(g) + u = src(e) + v = dst(e) + Graphs.add_edge!(sg, u, v) + end + N = length(membership) + lx = zeros(N) + ly = zeros(N) + comms = Dict{Int,Vector{Int}}() + for (idx,lbl) in enumerate(membership) + if haskey(comms, lbl) + push!(comms[lbl], idx) + else + comms[lbl] = Int[idx] + end + end + h = collapse_graph(g, membership)[1] + clx, cly = spring_layout(h) + for (lbl, nodes) in comms + subg = sg[nodes] + sublx, subly = spring_layout(subg) + for (idx, node) in enumerate(nodes) + lx[node] = 1.8*length(nodes)/N*sublx[idx] + clx[lbl] + ly[node] = 1.8*length(nodes)/N*subly[idx] + cly[lbl] + end + end + return lx, ly +end + +function collapse_graph(g::AbstractGraph, membership::Vector{Int}) + nb_comm = maximum(membership) + + collapsed_edge_weights = Vector{Dict{Int,Float64}}(undef, nb_comm) + for i=1:nb_comm + collapsed_edge_weights[i] = Dict{Int,Float64}() + end + + for e in edges(g) + u = src(e) + v = dst(e) + u_comm = membership[u] + v_comm = membership[v] + + # for special case of undirected network + if !is_directed(g) + u_comm, v_comm = minmax(u_comm, v_comm) + end + + if haskey(collapsed_edge_weights[u_comm], v_comm) + collapsed_edge_weights[u_comm][v_comm] += 1 + else + collapsed_edge_weights[u_comm][v_comm] = 1 + end + end + + collapsed_graph = SimpleGraph(nb_comm) + collapsed_weights = Float64[] + + for u=1:nb_comm + for (v,w) in collapsed_edge_weights[u] + add_edge!(collapsed_graph, u, v) + push!(collapsed_weights, w) + end + end + + return collapsed_graph, collapsed_weights +end \ No newline at end of file diff --git a/src/pienode.jl b/src/pienode.jl deleted file mode 100644 index dbafe5b..0000000 --- a/src/pienode.jl +++ /dev/null @@ -1,41 +0,0 @@ -# to do -mutable struct PIENODE - x::Float64 - y::Float64 - r::Float64 - prop::Vector{Float64} - colors - strokes -end - -function pie(pn::PIENODE) - p = [0.0;2pi*pn.prop/sum(pn.prop)] - θ = cumsum(p) - s = Vector[] - for i=1:length(θ)-1 - push!(s, sector(pn.x, pn.y, pn.r, θ[i], θ[i+1])) - end - compose(context(),path(s), fill(pn.colors), stroke(pn.strokes)) -end - -function sector(x, y, r, θ1, θ2) - if θ2-θ1<=pi - [:M, x+r*cos(θ1),y-r*sin(θ1), :A, r, r, 0, false, false, x+r*cos(θ2), y-r*sin(θ2), :L, x, y, :Z] - else - [ - :M, x+r*cos(θ1),y-r*sin(θ1), - :A, r, r, 0, false, false, x+r*cos(θ1+pi), y-r*sin(θ1+pi), - :A, r, r, 0, false, false, x+r*cos(θ2), y-r*sin(θ2), - :L, x, y, - :Z - ] - end -end - -function sector(x::Vector{T}, y::Vector{T}, r::Vector{T}, θ1::Vector{T}, θ2::Vector{T}) where {T} - s = Vector[] - for i=1:length(x) - push!(s, sector(x[i],y[i],r[i],θ1[i],θ2[i])) - end - s -end diff --git a/src/plot.jl b/src/plot.jl index 1df938b..7b0d36d 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -20,7 +20,7 @@ be obtained from `layout` kwarg. `layout` Layout algorithm. Currently can be one of [`random_layout`, `circular_layout`, `spring_layout`, `shell_layout`, `stressmajorize_layout`, -`spectral_layout`]. +`spectral_layout`, `community_layout`]. Default: `spring_layout` `max_nodesize` diff --git a/src/shape.jl b/src/shape.jl deleted file mode 100644 index a3e6549..0000000 --- a/src/shape.jl +++ /dev/null @@ -1,9 +0,0 @@ -# draw a regular n-gon -function ngon(x, y, r, n=3, θ=0.0) - αs = linspace(0,2pi,n+1)[1:end-1] - [(r*cos(α-θ)+x, r*sin(α-θ)+y) for α in αs] -end - -function ngon(xs::Vector, ys::Vector, rs::Vector, ns::Vector=fill(3,length(xs)), θs::Vector=zeros(length(xs))) - [ngon(xs[i], ys[i], rs[i], ns[i], θs[i]) for i=1:length(xs)] -end diff --git a/src/stress.jl b/src/stress.jl deleted file mode 100644 index f09c708..0000000 --- a/src/stress.jl +++ /dev/null @@ -1,175 +0,0 @@ -using LinearAlgebra - -# This layout algorithm is copy from [IainNZ](https://github.com/IainNZ)'s [GraphLayout.jl](https://github.com/IainNZ/GraphLayout.jl) -@doc """ -Compute graph layout using stress majorization - -Inputs: - - δ: Matrix of pairwise distances - p: Dimension of embedding (default: 2) - w: Matrix of weights. If not specified, defaults to - w[i,j] = δ[i,j]^-2 if δ[i,j] is nonzero, or 0 otherwise - X0: Initial guess for the layout. Coordinates are given in rows. - If not specified, default to random matrix of Gaussians - -Additional optional keyword arguments control the convergence of the algorithm -and the additional output as requested: - - maxiter: Maximum number of iterations. Default: 400size(X0, 1)^2 - abstols: Absolute tolerance for convergence of stress. - The iterations terminate if the difference between two - successive stresses is less than abstol. - Default: √(eps(eltype(X0)) - reltols: Relative tolerance for convergence of stress. - The iterations terminate if the difference between two - successive stresses relative to the current stress is less than - reltol. Default: √(eps(eltype(X0)) - abstolx: Absolute tolerance for convergence of layout. - The iterations terminate if the Frobenius norm of two successive - layouts is less than abstolx. Default: √(eps(eltype(X0)) - verbose: If true, prints convergence information at each iteration. - Default: false - returnall: If true, returns all iterates and their associated stresses. - If false (default), returns the last iterate - -Output: - - The final layout X, with coordinates given in rows, unless returnall=true. - -Reference: - - The main equation to solve is (8) of: - - @incollection{ - author = {Emden R Gansner and Yehuda Koren and Stephen North}, - title = {Graph Drawing by Stress Majorization} - year={2005}, - isbn={978-3-540-24528-5}, - booktitle={Graph Drawing}, - seriesvolume={3383}, - series={Lecture Notes in Computer Science}, - editor={Pach, J\'anos}, - doi={10.1007/978-3-540-31843-9_25}, - publisher={Springer Berlin Heidelberg}, - pages={239--250}, - } -""" -function stressmajorize_layout(g::AbstractGraph, - p::Int=2, - w=nothing, - X0=randn(nv(g), p); - maxiter = 400size(X0, 1)^2, - abstols=√(eps(eltype(X0))), - reltols=√(eps(eltype(X0))), - abstolx=√(eps(eltype(X0))), - verbose = false, - returnall = false) - - @assert size(X0, 2)==p - δ = fill(1.0, nv(g), nv(g)) - - if w == nothing - w = δ.^-2 - w[.!isfinite.(w)] .= 0 - end - - @assert size(X0, 1)==size(δ, 1)==size(δ, 2)==size(w, 1)==size(w, 2) - Lw = weightedlaplacian(w) - pinvLw = pinv(Lw) - newstress = stress(X0, δ, w) - Xs = Matrix[X0] - stresses = [newstress] - iter = 0 - for outer iter = 1:maxiter - #TODO the faster way is to drop the first row and col from the iteration - X = pinvLw * (LZ(X0, δ, w)*X0) - @assert all(isfinite.(X)) - newstress, oldstress = stress(X, δ, w), newstress - verbose && @info("""Iteration $iter - Change in coordinates: $(norm(X - X0)) - Stress: $newstress (change: $(newstress-oldstress)) - """) - push!(Xs, X) - push!(stresses, newstress) - abs(newstress - oldstress) < reltols * newstress && break - abs(newstress - oldstress) < abstols && break - norm(X - X0) < abstolx && break - X0 = X - end - iter == maxiter && @warn("Maximum number of iterations reached without convergence") - #returnall ? (Xs, stresses) : Xs[end] - Xs[end][:,1], Xs[end][:,2] -end - -@doc """ -Stress function to majorize - -Input: - X: A particular layout (coordinates in rows) - d: Matrix of pairwise distances - w: Weights for each pairwise distance - -See (1) of Reference -""" -function stress(X, d=fill(1.0, size(X, 1), size(X, 1)), w=nothing) - s = 0.0 - n = size(X, 1) - if w==nothing - w = d.^-2 - w[!isfinite.(w)] = 0 - end - @assert n==size(d, 1)==size(d, 2)==size(w, 1)==size(w, 2) - for j=1:n, i=1:j-1 - s += w[i, j] * (norm(X[i,:] - X[j,:]) - d[i,j])^2 - end - @assert isfinite(s) - return s -end - -@doc """ -Compute weighted Laplacian given ideal weights w - -Lʷ defined in (4) of the Reference -""" -function weightedlaplacian(w) - n = LinearAlgebra.checksquare(w) - T = eltype(w) - Lw = zeros(T, n, n) - for i=1:n - D = zero(T) - for j=1:n - i==j && continue - Lw[i, j] = -w[i, j] - D += w[i, j] - end - Lw[i, i] = D - end - return Lw -end - -@doc """ -Computes L^Z defined in (5) of the Reference - -Input: Z: current layout (coordinates) - d: Ideal distances (default: all 1) - w: weights (default: d.^-2) -""" -function LZ(Z, d, w) - n = size(Z, 1) - L = zeros(n, n) - for i=1:n - D = 0.0 - for j=1:n - i==j && continue - nrmz = norm(Z[i,:] - Z[j,:]) - nrmz==0 && continue - δ = w[i, j] * d[i, j] - L[i, j] = -δ/nrmz - D -= -δ/nrmz - end - L[i, i] = D - end - @assert all(isfinite.(L)) - L -end From 67bd950938f19c6c00eb5a0ff659745c6a43a1b4 Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Wed, 27 Jul 2022 09:50:55 -0500 Subject: [PATCH 13/18] Fix #154 Multiple dispatch was messing up because types were not specified for spring layout and `kws` not preceeded by `;` --- src/layout.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/layout.jl b/src/layout.jl index 5507b89..85320d1 100644 --- a/src/layout.jl +++ b/src/layout.jl @@ -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) @@ -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 From 22cddebcea3c609631b0703effd64412dff79891 Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Wed, 27 Jul 2022 10:37:05 -0500 Subject: [PATCH 14/18] make default consistent with gplot notation (pi/9) --- src/lines.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lines.jl b/src/lines.jl index 4589641..8b1a857 100644 --- a/src/lines.jl +++ b/src/lines.jl @@ -180,7 +180,7 @@ function graphcurve(g::AbstractGraph{T}, locs_x, locs_y, nodesize::Vector{<:Real end # this function is copy from [IainNZ](https://github.com/IainNZ)'s [GraphLayout.jl](https://github.com/IainNZ/GraphLayout.jl) -function arrowcoords(θ, endx, endy, arrowlength, angleoffset=20.0/180.0*π) +function arrowcoords(θ, endx, endy, arrowlength, angleoffset=π/9) arr1x = endx - arrowlength*cos(θ+angleoffset) arr1y = endy - arrowlength*sin(θ+angleoffset) arr2x = endx - arrowlength*cos(θ-angleoffset) From 6f4597f5d3323016ae65de56efdcd9ecc1eafd93 Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Tue, 2 Aug 2022 09:32:47 -0500 Subject: [PATCH 15/18] Revert "Fix #154" This reverts commit 67bd950938f19c6c00eb5a0ff659745c6a43a1b4. --- src/layout.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/layout.jl b/src/layout.jl index 85320d1..5507b89 100644 --- a/src/layout.jl +++ b/src/layout.jl @@ -102,11 +102,11 @@ julia> locs_x, locs_y = spring_layout(g) ``` """ function spring_layout(g::AbstractGraph, - locs_x::Vector{R1}=2*rand(nv(g)).-1.0, - locs_y::Vector{R2}=2*rand(nv(g)).-1.0; + locs_x=2*rand(nv(g)).-1.0, + locs_y=2*rand(nv(g)).-1.0; C=2.0, MAXITER=100, - INITTEMP=2.0) where {R1 <: Real, R2 <: Real} + INITTEMP=2.0) nvg = nv(g) adj_matrix = adjacency_matrix(g) @@ -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 From 40e21beec22dcc7128c36af2adae5082c0482f26 Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Tue, 2 Aug 2022 09:33:34 -0500 Subject: [PATCH 16/18] Revert "bug fix" Remove commits that are in separate PRs This reverts commit d4a2ae4ba42a701ebe49865d2addf212c54f7bd7. --- README.md | 1 - src/plot.jl | 35 ++++++++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f012ea5..f34804c 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,6 @@ 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)` -+ `backgroundc` Color for the plot background. Default: `nothing` # Reporting Bugs diff --git a/src/plot.jl b/src/plot.jl index 7b0d36d..c9d650d 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -41,11 +41,16 @@ Distances for the node labels from center of nodes. Default: `0.0` `nodelabelangleoffset` Angle offset for the node labels (only used when `nodelabeldist` is not zero). Default: `π/4.0` +<<<<<<< HEAD `max_nodelabelsize` Largest fontsize for the vertex labels. Default: `4.0` +======= +`NODELABELSIZE` +Largest fontsize for the vertice labels. Default: `4.0` +>>>>>>> parent of 14d62b4 (Fix #172. set background color (`backgroundc` kwarg):) `nodelabelsize` -Relative fontsize for the vertex labels, can be a Vector. Default: `1.0` +Relative fontsize for the vertice labels, can be a Vector. Default: `1.0` `nodefillc` Color to fill the nodes with, can be a Vector. Default: `colorant"turquoise"` @@ -94,9 +99,6 @@ 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)` -`backgroundc` -Color for the plot background. Default: `nothing` - """ function gplot(g::AbstractGraph{T}, locs_x_in::Vector{R1}, locs_y_in::Vector{R2}; @@ -122,9 +124,14 @@ function gplot(g::AbstractGraph{T}, nodestrokelw = 0.0, arrowlengthfrac = is_directed(g) ? 0.1 : 0.0, arrowangleoffset = π / 9, +<<<<<<< HEAD linetype = :straight, outangle = π / 5, backgroundc = nothing) where {T <:Integer, R1 <: Real, R2 <: Real} +======= + linetype = "straight", + outangle = π / 5) where {T <:Integer, R1 <: Real, R2 <: Real} +>>>>>>> parent of 14d62b4 (Fix #172. set background color (`backgroundc` kwarg):) @assert length(locs_x_in) == length(locs_y_in) == nv(g) "Position vectors must be of the same length as the number of nodes" @assert isnothing(nodelabel) || length(nodelabel) == nv(g) "`nodelabel` must either be `nothing` or a vector of the same length as the number of nodes" @@ -157,12 +164,25 @@ function gplot(g::AbstractGraph{T}, end # Create nodes +<<<<<<< HEAD nodecircle = fill(0.4Compose.w, nv(g)) .* nodesize +======= + nodecircle = fill(0.4Compose.w, length(locs_x)) + if isa(nodesize, Real) + for i = 1:length(locs_x) + nodecircle[i] *= nodesize + end + else + for i = 1:length(locs_x) + nodecircle[i] *= nodesize[i] + end + end +>>>>>>> parent of 14d62b4 (Fix #172. set background color (`backgroundc` kwarg):) nodes = circle(locs_x, locs_y, nodecircle) # Create node labels if provided texts = nothing - if !isnothing(nodelabel) + if nodelabel != nothing text_locs_x = deepcopy(locs_x) text_locs_y = deepcopy(locs_y) texts = text(text_locs_x .+ nodesize .* (nodelabeldist * cos(nodelabelangleoffset)), @@ -207,10 +227,15 @@ function gplot(g::AbstractGraph{T}, end end +<<<<<<< HEAD #build plot compose(context(units=UnitBox(-1.2, -1.2, +2.4, +2.4)), compose(context(), rectangle(-1.2, -1.2, +2.4, +2.4), fill(backgroundc)), compose(context(), texts, fill(nodelabelc), fontsize(nodelabelsize)), +======= + compose(context(units=UnitBox(-1.2, -1.2, +2.4, +2.4)), + compose(context(), texts, fill(nodelabelc), stroke(nothing), fontsize(nodelabelsize)), +>>>>>>> parent of 14d62b4 (Fix #172. set background color (`backgroundc` kwarg):) compose(context(), nodes, fill(nodefillc), stroke(nodestrokec), linewidth(nodestrokelw)), compose(context(), edgetexts, fill(edgelabelc), fontsize(edgelabelsize)), compose(context(), arrows, stroke(edgestrokec), linewidth(edgelinewidth)), From f4f375f9b266ec34ff15de54653437220ff9e208 Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Tue, 2 Aug 2022 09:47:06 -0500 Subject: [PATCH 17/18] Revert "bug fix" Remove commits that are in separate PRs This reverts commit d4a2ae4ba42a701ebe49865d2addf212c54f7bd7. --- src/plot.jl | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/src/plot.jl b/src/plot.jl index c9d650d..2107b8e 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -44,10 +44,6 @@ Angle offset for the node labels (only used when `nodelabeldist` is not zero). D <<<<<<< HEAD `max_nodelabelsize` Largest fontsize for the vertex labels. Default: `4.0` -======= -`NODELABELSIZE` -Largest fontsize for the vertice labels. Default: `4.0` ->>>>>>> parent of 14d62b4 (Fix #172. set background color (`backgroundc` kwarg):) `nodelabelsize` Relative fontsize for the vertice labels, can be a Vector. Default: `1.0` @@ -124,14 +120,8 @@ function gplot(g::AbstractGraph{T}, nodestrokelw = 0.0, arrowlengthfrac = is_directed(g) ? 0.1 : 0.0, arrowangleoffset = π / 9, -<<<<<<< HEAD linetype = :straight, - outangle = π / 5, - backgroundc = nothing) where {T <:Integer, R1 <: Real, R2 <: Real} -======= - linetype = "straight", outangle = π / 5) where {T <:Integer, R1 <: Real, R2 <: Real} ->>>>>>> parent of 14d62b4 (Fix #172. set background color (`backgroundc` kwarg):) @assert length(locs_x_in) == length(locs_y_in) == nv(g) "Position vectors must be of the same length as the number of nodes" @assert isnothing(nodelabel) || length(nodelabel) == nv(g) "`nodelabel` must either be `nothing` or a vector of the same length as the number of nodes" @@ -164,20 +154,7 @@ function gplot(g::AbstractGraph{T}, end # Create nodes -<<<<<<< HEAD nodecircle = fill(0.4Compose.w, nv(g)) .* nodesize -======= - nodecircle = fill(0.4Compose.w, length(locs_x)) - if isa(nodesize, Real) - for i = 1:length(locs_x) - nodecircle[i] *= nodesize - end - else - for i = 1:length(locs_x) - nodecircle[i] *= nodesize[i] - end - end ->>>>>>> parent of 14d62b4 (Fix #172. set background color (`backgroundc` kwarg):) nodes = circle(locs_x, locs_y, nodecircle) # Create node labels if provided @@ -227,15 +204,9 @@ function gplot(g::AbstractGraph{T}, end end -<<<<<<< HEAD #build plot compose(context(units=UnitBox(-1.2, -1.2, +2.4, +2.4)), - compose(context(), rectangle(-1.2, -1.2, +2.4, +2.4), fill(backgroundc)), compose(context(), texts, fill(nodelabelc), fontsize(nodelabelsize)), -======= - compose(context(units=UnitBox(-1.2, -1.2, +2.4, +2.4)), - compose(context(), texts, fill(nodelabelc), stroke(nothing), fontsize(nodelabelsize)), ->>>>>>> parent of 14d62b4 (Fix #172. set background color (`backgroundc` kwarg):) compose(context(), nodes, fill(nodefillc), stroke(nodestrokec), linewidth(nodestrokelw)), compose(context(), edgetexts, fill(edgelabelc), fontsize(edgelabelsize)), compose(context(), arrows, stroke(edgestrokec), linewidth(edgelinewidth)), From 1a945c4688930f2fb95eb9fba2f1378778ddbbf4 Mon Sep 17 00:00:00 2001 From: hdavid16 <hperez16@gmail.com> Date: Tue, 2 Aug 2022 09:47:31 -0500 Subject: [PATCH 18/18] no change . --- src/plot.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plot.jl b/src/plot.jl index 2107b8e..fe6e553 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -41,7 +41,6 @@ Distances for the node labels from center of nodes. Default: `0.0` `nodelabelangleoffset` Angle offset for the node labels (only used when `nodelabeldist` is not zero). Default: `π/4.0` -<<<<<<< HEAD `max_nodelabelsize` Largest fontsize for the vertex labels. Default: `4.0`