Skip to content
This repository has been archived by the owner on Jun 23, 2023. It is now read-only.

Example use case #172

Merged
merged 6 commits into from
Nov 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ makedocs(
"Random networks" => [
"Null models" => "random/null.md",
"Structural models" => "random/structure.md"
]
],
"Examples" => [
"Integration with Mangal" => "examples/integration_mangal.md"
]
]
)

Expand Down
126 changes: 126 additions & 0 deletions docs/src/examples/integration_mangal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Integration with Mangal.jl

In this example, we will show how `EcologicalNetworks.jl` can be integrated with [`Mangal.jl`](https://github.com/EcoJulia/Mangal.jl) to analyse many ecological networks. Specifically, we will show how to analyse the association between meaningful network properties (i.e. species richness, connectance, nestedness, and modularity) using all food webs archived on the [`mangal.io`](https://mangal.io/#/) online database.

To conduct this analysis, we need to upload the following packages:

```@example mangal
using EcologicalNetworks
using Mangal
using DataFrames
using Plots
```

We first retrieve relevant metadata for all networks archived on `mangal.io` using the `Mangal.jl` package. We count the number of species $S$ and the total number of interactions $L$ in each network, as well as their number of trophic interactions (predation and herbivory). We store these information in a data frame along with the networks' ID numbers.

```@example mangal
number_of_networks = count(MangalNetwork)
count_per_page = 100
number_of_pages = convert(Int, ceil(number_of_networks/count_per_page))

mangal_networks = DataFrame(fill(Int64, 5),
[:id, :S, :L, :pred, :herb],
number_of_networks)

global cursor = 1
@progress "Paging networks" for page in 1:number_of_pages
global cursor
networks_in_page = Mangal.networks("count" => count_per_page, "page" => page-1)
@progress "Counting items" for current_network in networks_in_page
S = count(MangalNode, current_network)
L = count(MangalInteraction, current_network)
pred = count(MangalInteraction, current_network, "type" => "predation")
herb = count(MangalInteraction, current_network, "type" => "herbivory")
mangal_networks[cursor,:] .= (current_network.id, S, L, pred, herb)
cursor = cursor + 1
end
end
```

We now have all the information we need to identify all food webs archived on `mangal.io`. Here we consider as food webs any ecological networks mainly composed of trophic interactions.

```@example mangal
mangal_foodwebs = mangal_networks[mangal_networks[!, :pred] .+ mangal_networks[!, :herb] ./ mangal_networks[!, :L] .> 0.5, :]
```

To analyse their properties, we first need to read all of these food webs using the `Mangal.jl` package, and then convert them to UnipartiteNetworks, when possible, using the `EcologicalNetworks.jl` package.

```@example mangal
mangal_foodwebs = network.(foodwebs.id)

unipartite_foodwebs = []

for i in eachindex(mangal_foodwebs)
try
unipartite_foodweb = convert(UnipartiteNetwork, mangal_foodwebs[i])
push!(unipartite_foodwebs, unipartite_foodweb)
catch
println("Cannot convert mangal food web $(i) to a unipartite network")
end
end
```

We can then compute any measure supported by `EcologicalNetworks.jl` for UnipartiteNetworks. In this example, we compute species richness, connectance, nestedness, and modularity. To compute network modularity, we use 100 random species assignments in 3 to 15 groups as our starters, the BRIM algorithm to optimize the modularity for each of these random partitions, and retain the maximum value for each food web.

```@example mangal
foodweb_measures = DataFrame(fill(Float64, 4),
[:rich, :connect, :nested, :modul],
length(unipartite_foodwebs))

# species richness
foodweb_measures.rich = richness.(unipartite_foodwebs)

# connectance
foodweb_measures.connect = connectance.(unipartite_foodwebs)

# nestedness
foodweb_measures.nested = ρ.(unipartite_foodwebs)

# modularity (BRIM algorithm)
number_of_modules = repeat(3:15, outer=100)
modules = Array{Dict}(undef, length(number_of_modules))

for i in eachindex(unipartite_foodwebs)
current_network = unipartite_foodwebs[i]
for j in eachindex(number_of_modules)
_, modules[j] = n_random_modules(number_of_modules[j])(current_network) |> x -> brim(x...)
end
partition_modularity = map(x -> Q(current_network,x), modules);
foodweb_measures.modul[i] = maximum(partition_modularity)
end
```

The association between these food-web measures can then be plotted. In each subplot, marker size is proportional to species richness.

```@example mangal
# color palette
pal=RGB(204/255,121/255,167/255)

plotA = scatter(foodweb_measures.connect, foodweb_measures.nested,
markersize=foodweb_measures.rich ./ 30,
alpha=0.6, color=pal,
lab="",
dpi=1000, framestyle=:box)
xaxis!("Connectance")
yaxis!((0.4,0.9), "Nestedness")

plotB = scatter(foodweb_measures.connect, foodweb_measures.modul,
markersize=foodweb_measures.rich ./ 30,
alpha=0.6, color=pal,
lab="",
dpi=1000, framestyle=:box)
xaxis!("Connectance")
yaxis!("Modularity")

plotC = scatter(foodweb_measures.modul, foodweb_measures.nested,
markersize=foodweb_measures.rich ./ 30,
alpha=0.6, color=pal,
lab="",
dpi=1000, framestyle=:box)
xaxis!("Modularity")
yaxis!((0.4,0.9), "Nestedness")

plot(plotA, plotB, plotC, layout=(1,3),
title=["($i)" for j in 1:1, i in 1:3], titleloc=:right, titlefont = font(12),
size=(700,350), margin=5Plots.mm)
```