1664869800

# NetworkViz.jl: Julia Interface to visualize Graphs

## NetworkViz

A Julia module to render graphs in 3D using ThreeJS tightly coupled with LightGraphs.

## Install

In a Julia REPL, run:

``````Pkg.add("NetworkViz")
``````

## Graph Primitives

### NodeProperty

The `NodeProperty` type stores the properties of each node in the graph. It stores the following properties :

• `color` : It is a `Colors` array that stores the colors of all the nodes in the graph.
• `size` : Size of the node. eg : `0.2`.
• `shape` : Shape of the node. Can be 0 or 1. `0 - Square`, `1 - Circle`.

### EdgeProperty

The `EdgeProperty` type stores the properties of each edge in the graph. It stores the following properties :

• `color` : It is a hex string that stores the color of the edges.
• `width` : Thickness of the edges. eg : `1.5`.

## Visualizing Graphs

The `drawGraph` function can be used to draw the graphs in 2D or 3D with nodes having different colors. It can accept `LightGraphs.Graph` and `LightGraphs.Digraph` types. `drawGraph` can be used to draw graphs from adjacency matrices also. The function accepts an additional kwargs `node::NodeProperty`, `edge::EdgeProperty`, and `z`. If `z=1`, it draws a 3D graph. If `z=0`, a 2D visualization of the graph is drawn. `node` and `edge` determines the properties of nodes and edges respectively.

Usage :

``````g = CompleteGraph(10)
c = Color[parse(Colorant,"#00004d") for i in 1:nv(g)]
n = NodeProperty(c,0.2,0)
e = EdgeProperty("#ff3333",1)
drawGraph(g,node=n,edge=e,z=1) #Draw using a Graph object (3D).

drawGraph(am,node=n,edge=e,z=0) #Draw using an adjacency matrix (2D).

dgraph = bfs_tree(g,1)
drawGraph(dgraph,z=1) #Draw a Digraph.
``````

## Utility Functions

• `addEdge(g::Graph,node1::Int,node2::Int,z=1)` - Add a new edge `node1-node2` and redraws the graph. `z` toggles 2D-3D conversion. Fails silently if an already existing node is added again.
• `removeEdge(g::Graph,node1::Int,node2::Int,z=1)` - Removes the edge `node1-node2` if it exists and redraws the graph. `z` toggles 2D-3D conversion.
• `addNode(g::Graph,z=1)` - Adds a new node to the graph. `z` toggles 2D-3D conversion.
• `removeNode(g::Graph,node::Int,z=1)` - Removes `node` if it exists and redraws the graph. `z` toggles 2D-3D conversion.

## Examples

``````#Run this code in Escher
using NetworkViz
using LightGraphs
main(window) = begin
push!(window.assets, "widgets")
push!(window.assets,("ThreeJS","threejs"))
g = CompleteGraph(10)
drawGraph(g)
end
``````

The above code produces the following output :

Here is another example with a code-mirror where functions can be typed in. Depending on the LightGraphs function used, 2D as well as 3D graphs are drawn. You can see the working demo here.

You can find many other examples in the `examples/` folder.

## Acknowledgement

IainNZ for the original Spring-Embedder code. (Taken from GraphLayout.jl).

Author: Abhijithanilkumar
Source Code: https://github.com/abhijithanilkumar/NetworkViz.jl

1664869800

## NetworkViz

A Julia module to render graphs in 3D using ThreeJS tightly coupled with LightGraphs.

## Install

In a Julia REPL, run:

``````Pkg.add("NetworkViz")
``````

## Graph Primitives

### NodeProperty

The `NodeProperty` type stores the properties of each node in the graph. It stores the following properties :

• `color` : It is a `Colors` array that stores the colors of all the nodes in the graph.
• `size` : Size of the node. eg : `0.2`.
• `shape` : Shape of the node. Can be 0 or 1. `0 - Square`, `1 - Circle`.

### EdgeProperty

The `EdgeProperty` type stores the properties of each edge in the graph. It stores the following properties :

• `color` : It is a hex string that stores the color of the edges.
• `width` : Thickness of the edges. eg : `1.5`.

## Visualizing Graphs

The `drawGraph` function can be used to draw the graphs in 2D or 3D with nodes having different colors. It can accept `LightGraphs.Graph` and `LightGraphs.Digraph` types. `drawGraph` can be used to draw graphs from adjacency matrices also. The function accepts an additional kwargs `node::NodeProperty`, `edge::EdgeProperty`, and `z`. If `z=1`, it draws a 3D graph. If `z=0`, a 2D visualization of the graph is drawn. `node` and `edge` determines the properties of nodes and edges respectively.

Usage :

``````g = CompleteGraph(10)
c = Color[parse(Colorant,"#00004d") for i in 1:nv(g)]
n = NodeProperty(c,0.2,0)
e = EdgeProperty("#ff3333",1)
drawGraph(g,node=n,edge=e,z=1) #Draw using a Graph object (3D).

drawGraph(am,node=n,edge=e,z=0) #Draw using an adjacency matrix (2D).

dgraph = bfs_tree(g,1)
drawGraph(dgraph,z=1) #Draw a Digraph.
``````

## Utility Functions

• `addEdge(g::Graph,node1::Int,node2::Int,z=1)` - Add a new edge `node1-node2` and redraws the graph. `z` toggles 2D-3D conversion. Fails silently if an already existing node is added again.
• `removeEdge(g::Graph,node1::Int,node2::Int,z=1)` - Removes the edge `node1-node2` if it exists and redraws the graph. `z` toggles 2D-3D conversion.
• `addNode(g::Graph,z=1)` - Adds a new node to the graph. `z` toggles 2D-3D conversion.
• `removeNode(g::Graph,node::Int,z=1)` - Removes `node` if it exists and redraws the graph. `z` toggles 2D-3D conversion.

## Examples

``````#Run this code in Escher
using NetworkViz
using LightGraphs
main(window) = begin
push!(window.assets, "widgets")
push!(window.assets,("ThreeJS","threejs"))
g = CompleteGraph(10)
drawGraph(g)
end
``````

The above code produces the following output :

Here is another example with a code-mirror where functions can be typed in. Depending on the LightGraphs function used, 2D as well as 3D graphs are drawn. You can see the working demo here.

You can find many other examples in the `examples/` folder.

## Acknowledgement

IainNZ for the original Spring-Embedder code. (Taken from GraphLayout.jl).

Author: Abhijithanilkumar
Source Code: https://github.com/abhijithanilkumar/NetworkViz.jl

1666064340

## Metis

Metis.jl is a Julia wrapper to the Metis library which is a library for partitioning unstructured graphs, partitioning meshes, and computing fill-reducing orderings of sparse matrices.

## Graph partitioning

`Metis.partition` calculates graph partitions. As an example, here we partition a small graph into two, three and four parts, and visualize the result:

`Metis.partition` calls `METIS_PartGraphKway` or `METIS_PartGraphRecursive` from the Metis C API, depending on the optional keyword argument `alg`:

• `alg = :KWAY`: multilevel k-way partitioning (`METIS_PartGraphKway`).
• `alg = :RECURSIVE`: multilevel recursive bisection (`METIS_PartGraphRecursive`).

## Vertex separator

`Metis.separator` calculates a vertex separator of a graph. `Metis.separator` calls `METIS_ComputeVertexSeparator` from the Metis C API. As an example, here we calculate a vertex separator (green) of a small graph:

## Fill reducing permutation

`Metis.permutation` calculates the fill reducing permutation for a sparse matrices. `Metis.permutation` calls `METIS_NodeND` from the Metis C API. As an example, we calculate the fill reducing permutation for a sparse matrix `S` originating from a typical (small) FEM problem, and visualize the sparsity pattern for the original matrix and the permuted matrix:

``````perm, iperm = Metis.permutation(S)
``````

We can also visualize the sparsity pattern of the Cholesky factorization of the same matrix. It is here clear that using the fill reducing permutation results in a sparser factorization:

## Direct access to the Metis C API

For more fine tuned usage of Metis consider calling the C API directly. The following functions are currently exposed:

• `METIS_PartGraphRecursive`
• `METIS_PartGraphKway`
• `METIS_ComputeVertexSeparator`
• `METIS_NodeND`

all with the same arguments and argument order as described in the Metis manual.

Author: JuliaSparse
Source Code: https://github.com/JuliaSparse/Metis.jl

1665083280

## GraphVisualize

Graph visualization using `GLVisualize.jl` by Simon Danisch. Tightly integrated with `LightGraphs.jl`.

This is a pre-alpha version.

## Install

``````Pkg.clone("https://github.com/JuliaGraphs/GraphVisualize.jl")
Pkg.checkout("GLVisualize")
Pkg.checkout("GLAbstraction")
``````

## Usage

For the time being only the function

``````    plot(g::Graph; observe=false)
``````

returning an plot object of graph `g` and visualizing it in an OpenGL window.

Is `observe=true` updates to `g` will be reflected in updates to the plot.

You can left-click and drag a vertex to move it around.

``````using LightGraphs
using GraphVisualize

g = erdos_renyi(10, 20)
plt = plot(g, observe=true)   # a windows pops up displaying g

add_edge!(g, 3, 7)      # the plot is updated
rem_edge!(g, 3, 7)      # the plot is updated
rem_vertex!(g, 3)       # the plot is updated
add_vertex!(g)          # the plot is updated

# have fun moving the vertex around

# now close the window
g = WheelGraph(10) # create a new graph, DON'T ever plot twice the same graph
plt = plot(g, observe=false)   # a windows pops up displaying g
add_edge!(g, 3, 7)      # the plot is NOT updated
push!(obs, g)           # the plot is updated
...``````

Author: CarloLucibello
Source Code: https://github.com/CarloLucibello/GraphVisualize.jl

1665122040

## GraphPlot

Graph layout and visualization algorithms based on Compose.jl and inspired by GraphLayout.jl.

The `spring_layout` and `stressmajorize_layout` function are copy from IainNZ's GraphLayout.jl.

Other layout algorithms are wrapped from NetworkX.

`gadfly.js` is copied from Gadfly.jl

Getting Started

From the Julia REPL the latest version can be installed with

``````Pkg.add("GraphPlot")
``````

GraphPlot is then loaded with

``````using GraphPlot
``````

Usage

## karate network

``````using Graphs: smallgraph
g = smallgraph(:karate)
gplot(g)
``````

## Add node label

``````using Graphs
nodelabel = 1:nv(g)
gplot(g, nodelabel=nodelabel)
``````

## Adjust node labels

``````gplot(g, nodelabel=nodelabel, nodelabeldist=1.5, nodelabelangleoffset=π/4)
``````

## Control the node size

``````# nodes size proportional to their degree
nodesize = [Graphs.outdegree(g, v) for v in Graphs.vertices(g)]
gplot(g, nodesize=nodesize)
``````

## Control the node color

Feed the keyword argument `nodefillc` a color array, ensure each node has a color. `length(nodefillc)` must be equal `|V|`.

``````using Colors

# Generate n maximally distinguishable colors in LCHab space.
nodefillc = distinguishable_colors(nv(g), colorant"blue")
gplot(g, nodefillc=nodefillc, nodelabel=nodelabel, nodelabeldist=1.8, nodelabelangleoffset=π/4)
``````

## Transparent

``````# stick out large degree nodes
alphas = nodesize/maximum(nodesize)
nodefillc = [RGBA(0.0,0.8,0.8,i) for i in alphas]
gplot(g, nodefillc=nodefillc)
``````

## Control the node label size

``````nodelabelsize = nodesize
gplot(g, nodelabelsize=nodelabelsize, nodesize=nodesize, nodelabel=nodelabel)
``````

## Draw edge labels

``````edgelabel = 1:Graphs.ne(g)
gplot(g, edgelabel=edgelabel, nodelabel=nodelabel)
``````

## Adjust edge labels

``````edgelabel = 1:Graphs.ne(g)
gplot(g, edgelabel=edgelabel, nodelabel=nodelabel, edgelabeldistx=0.5, edgelabeldisty=0.5)
``````

## Color the graph

``````# nodes membership
membership = [1,1,1,1,1,1,1,1,2,1,1,1,1,1,2,2,1,1,2,1,2,1,2,2,2,2,2,2,2,2,2,2,2,2]
nodecolor = [colorant"lightseagreen", colorant"orange"]
# membership color
nodefillc = nodecolor[membership]
gplot(g, nodefillc=nodefillc)
``````

## Different layout

### spring layout (default)

This is the defaut layout and will be chosen if no layout is specified. The default parameters to the spring layout algorithm can be changed by supplying an anonymous function, e.g., if nodes appear clustered too tightly together, try

``````layout=(args...)->spring_layout(args...; C=20)
gplot(g, layout=layout, nodelabel=nodelabel)
``````

where `C` influences the desired distance between nodes.

### random layout

``````gplot(g, layout=random_layout, nodelabel=nodelabel)
``````

### circular layout

``````gplot(g, layout=circular_layout, nodelabel=nodelabel)
``````

### spectral layout

``````gplot(g, layout=spectral_layout)
``````

### shell layout

``````nlist = Vector{Vector{Int}}(undef, 2) # two shells
nlist[1] = 1:5 # first shell
nlist[2] = 6:nv(g) # second shell
locs_x, locs_y = shell_layout(g, nlist)
gplot(g, locs_x, locs_y, nodelabel=nodelabel)
``````

## Curve edge

``````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

``````using Compose
# save to pdf
draw(PDF("karate.pdf", 16cm, 16cm), gplot(g))
# save to png
draw(PNG("karate.png", 16cm, 16cm), gplot(g))
# save to svg
draw(SVG("karate.svg", 16cm, 16cm), gplot(g))
``````

Graphs.jl integration

``````using Graphs
h = watts_strogatz(50, 6, 0.3)
gplot(h)
``````

Arguments

• `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

Filing an issue to report a bug, counterintuitive behavior, or even to request a feature is extremely valuable in helping me prioritize what to work on, so don't hestitate.

Author: JuliaGraphs
Source Code: https://github.com/JuliaGraphs/GraphPlot.jl

1656899776

## graph-scroll.js

Simple scrolling events for d3 graphs. Based on stack

### Demo/Documentation

graph-scroll takes a selection of explanatory text sections and dispatches `active` events as different sections are scrolled into to view. These `active` events can be used to update a chart's state.

``````d3.graphScroll()
.sections(d3.selectAll('#sections > div'))
.on('active', function(i){ console.log(i + 'th section active') })
``````

The top most element scrolled fully into view is classed `graph-scroll-active`. This makes it easy to highlight the active section with css:

``````#sections > div{
opacity: .3
}

#sections div.graph-scroll-active{
opacity: 1;
}
``````

To support headers and intro images/text, we use a container element containing the explanatory text and graph.

``````<h1>Page Title</div>
<div id='container'>
<div id='graph'></div>
<div id='sections'>
<div>Section 0</div>
<div>Section 1</div>
<div>Section 2</div>
</div>
</div>
<h1>Footer</h1>
``````

If these elements are passed to graphScroll as selections with `container` and `graph`, every element in the graph selection will be classed `graph-scroll-graph` if the top of the container is out of view.

``````d3.graphScroll()
.graph(d3.selectAll('#graph'))
.container(d3.select('#container'))
.sections(d3.selectAll('#sections > div'))
.on('active', function(i){ console.log(i + 'th section active') })

``````

When the graph starts to scroll out of view, `position: sticky` keeps the graph element stuck to the top of the page while the text scrolls by.

``````#container{
position: relative;
}

#sections{
width: 340px;
}

#graph{
margin-left: 40px;
width: 500px;
position: sticky;
top: 0px;
float: right;
}
``````

On mobile centering the graph and sections while adding a some padding for the first slide is a good option:

``````@media (max-width: 925px)  {
#graph{
width: 100%;
margin-left: 0px;
float: none;
}

#sections{
position: relative;
margin: 0px auto;
}
}
``````

Adjust the amount of pixels before a new section is triggered is also helpful on mobile (Defaults to 200 pixels):

``````graphScroll.offset(300)
``````

To update or replace a graphScroll instance, pass a string to `eventId` to remove the old event listeners:

``graphScroll.eventId('uniqueId1')``

Author: 1wheel
Source Code: https://github.com/1wheel/graph-scroll