Creating the initial layout

The first step is to generate a starting position for the nodes in the network. In a lot of cases, this is a pseudo-random position, which is then refined. The methods for every layouts have different initial conditions.

initial(::Type{RandomInitialLayout}, N::T) where {T <: EcologicalNetworks.AbstractEcologicalNetwork}

Random disposition of nodes in a circle. This is a good starting point for any force-directed layout. The circle is scaled so that its radius is twice the square root of the network richness, which helps most layouts converge faster.

initial(::Type{BipartiteInitialLayout}, N::T) where {T <: EcologicalNetworks.AbstractBipartiteNetwork}

Random disposition of nodes on two levels for bipartite networks.

initial(::Type{FoodwebInitialLayout}, N::T) where {T <: EcologicalNetworks.AbstractUnipartiteNetwork}

Random disposition of nodes on trophic levels for food webs. Note that the continuous trophic level is used, but the layout can be modified afterwards to use another measure of trophic rank.

initial(::Type{CircularInitialLayout}, N::T) where {T <: EcologicalNetworks.AbstractEcologicalNetwork}

Random disposition of nodes on a circle. This is the starting point for circle-based layouts.

initial(::Type{UnravelledInitialLayout}, N::T) where {T <: EcologicalNetworks.AbstractUnipartiteNetwork}

Unravelled disposition of nodes on trophic levels for food webs, where the x axis is the omnivory index. Note that the fractional trophic level is used, but the layout can be modified afterwards to use the continuous levels. See the documentation for UnravelledLayout to see how.

Applying the layout

The second step is to apply the layout. In most cases, this only needs to be done once. Force-directed layouts can require a very large number of iterations, and also tend to scale very poorly with the size of the network.

position!(LA::ForceDirectedLayout, L::Dict{K,NodePosition}, N::T) where {T <: EcologicalNetworks.AbstractEcologicalNetwork} where {K}

One iteration of the force-directed layout routine. Because these algorithms can take some time to converge, it may be useful to stop every 500 iterations to have a look at the results. Note that to avoid oscillations, the maximum displacement at any given time is set to 0.01 units.

These layouts tend to have O(N³) complexity, where N is the number of nodes in the network. This is because repulsion required to do (N×(N-1))/2 visits on pairs of nodes, and an optimal layout usually requires s×N steps to converge. With the maximal displacement set to 0.01, we have found that k ≈ 100 gives acceptable results. This will depend on the complexity of the network, and its connectance, as well as the degree and edge strengths distributions.

position!(LA::LT, L::Dict{K,NodePosition}, N::T) where {LT <: UnravelledLayout, T <: AbstractEcologicalNetwork} where {K}

Position species according to the function defined in the UnravelledLayout.

position!(LA::NestedBipartiteLayout, L::Dict{K,NodePosition}, N::T) where {T <: AbstractBipartiteNetwork} where {K}

Rank species according to their degree.

position!(LA::CircularLayout, L::Dict{K,NodePosition}, N::T) where {T <: AbstractEcologicalNetwork} where {K}

Nodes will be positioned at equal distances along a circle, and nodes that are densely connected will be closer to one another. This is an efficient way to represent modular networks.


McGuffin, M.J., 2012. Simple algorithms for network visualization: A tutorial. Tsinghua Science and Technology 17, 383–398.