This repository has been archived by the owner on Jun 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #175 from EcoJulia/doc/examples
Additional examples
- Loading branch information
Showing
13 changed files
with
415 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
name: Documentation | ||
|
||
on: | ||
release: | ||
push: | ||
branches: | ||
- master | ||
tags: '*' | ||
pull_request: | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: julia-actions/setup-julia@latest | ||
with: | ||
version: '1.5' | ||
- name: Install dependencies | ||
run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' | ||
- name: Build and deploy | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.TOKEN }} # For authentication with GitHub Actions token | ||
run: julia --project=docs/ docs/make.jl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
|
||
# Network beta-diversity | ||
|
||
In this section, we will measure the dissimilarity between bipartite | ||
host-parasite networks. | ||
|
||
```@example betadiv | ||
using EcologicalNetworks | ||
using Plots | ||
using Plots.PlotMeasures | ||
``` | ||
|
||
We use networks that span the entirety of Eurasia. Because these networks are | ||
originally quantitative, we will remove the information on interaction strength | ||
using `convert`. Note that we convert to an union type (`BinaryNetwork`) -- the | ||
`convert` function will select the appropriate network type to return based on | ||
the partiteness. The core operations on sets (`union`, `diff`, and `intersect`) | ||
are implemented for the `BinaryNetwork` type. As such, generating the "metaweb" | ||
(*i.e.* the list of all species and all interactions in the complete dataset) | ||
is: | ||
|
||
```@example betadiv | ||
all_hp_data = filter(x -> occursin("Hadfield", x.Reference), web_of_life()); | ||
ids = getfield.(all_hp_data, :ID); | ||
networks = convert.(BinaryNetwork, web_of_life.(ids)); | ||
metaweb = reduce(union, networks) | ||
``` | ||
|
||
From this metaweb, we can measure $\beta_{OS}'$, *i.e.* the dissimilarity of | ||
every network to the expectation in the metaweb. Measuring the distance between | ||
two networks is done in two steps. Dissimilarity is first partitioned into three | ||
components (common elements, and elements unique to both samples), then the | ||
value is measured based on the cardinality of these components. The functions to | ||
generate the partitions are `βos` (dissimilarity of interactions between shared | ||
species), `βs` (dissimilarity of species composition), and `βwn` (whole network | ||
dissimilarity). The output of these functions is passed to one of the functions | ||
to measure the actual $β$-diversity. | ||
|
||
```@example betadiv | ||
βcomponents = [βos(metaweb, n) for n in networks]; | ||
βosprime = KGL02.(βcomponents); | ||
``` | ||
|
||
Finally, we measure the pairwise distance between all networks (because we use a | ||
symmetric measure, we only need $n\times(n-1)$ distances): | ||
|
||
```@example betadiv | ||
S, OS, WN = Float64[], Float64[], Float64[] | ||
for i in 1:(length(networks)-1) | ||
for j in (i+1):length(networks) | ||
push!(S, KGL02(βs(networks[i], networks[j]))) | ||
push!(OS, KGL02(βos(networks[i], networks[j]))) | ||
push!(WN, KGL02(βwn(networks[i], networks[j]))) | ||
end | ||
end | ||
``` | ||
|
||
We can now visualize these data: | ||
|
||
```@example betadiv | ||
p1 = histogram(βosprime, frame=:origin, bins=20, c=:white, leg=false, grid=false, margin=10mm) | ||
xaxis!(p1, "Difference to metaweb", (0,1)) | ||
yaxis!(p1, (0,10)) | ||
p2 = plot([0,1],[0,1], c=:grey, ls=:dash, frame=:origin, grid=false, lab="", legend=:bottomleft, margin=10mm) | ||
scatter!(p2, S, OS, mc=:black, lab="shared sp.", msw=0.0) | ||
scatter!(p2, S, WN, mc=:lightgrey, lab="all sp.", msw=0.0, m=:diamond) | ||
xaxis!(p2, "Species dissimilarity", (0,1)) | ||
yaxis!(p2, "Network dissimilarity", (0,1)) | ||
plot(p1,p2, size=(700,300)) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
In this illustration, we will simulate extinctions of hosts, to show how the | ||
package can be extended by using the core functions described in the "Interface" | ||
section. Simply put, the goal of this example is to write a function to randomly | ||
remove one host species, remove all parasite species that end up not connected | ||
to a host, and measuring the effect of these extinctions on the remaining | ||
network. Rather than measuring the network structure in the function, we will | ||
return an array of networks to be manipulated later: | ||
|
||
```@example ext | ||
using EcologicalNetworks | ||
using Plots | ||
using Plots.PlotMeasures | ||
``` | ||
|
||
```@example ext | ||
function extinctions(N::T) where {T <: AbstractBipartiteNetwork} | ||
# We start by making a copy of the network to extinguish | ||
Y = [copy(N)] | ||
# While there is at least one species remaining... | ||
while richness(last(Y)) > 1 | ||
# We remove one species randomly | ||
remain = sample(species(last(Y); dims=2), richness(last(Y); dims=2)-1, replace=false) | ||
# Remaining species | ||
R = last(Y)[:,remain] | ||
simplify!(R) | ||
# Then add the simplified network (without the extinct species) to our collection | ||
push!(Y, copy(R)) | ||
end | ||
return Y | ||
end | ||
``` | ||
|
||
One classical analysis is to remove host species, and count the richness of | ||
parasite species, to measure their robustness to host extinctions -- this is | ||
usually done with multiple scenarios for order of extinction, but we will focus | ||
on the random order here. Even though `EcologicalNetworks` has a built-in | ||
function for richness, we can write a small wrapper around it: | ||
|
||
```@example ext | ||
function parasite_richness(N::T) where {T<:BinaryNetwork} | ||
return richness(N; dims=1) | ||
end | ||
``` | ||
|
||
Writing multiple functions that take a single argument allows to chain them in a | ||
very expressive way: for example, measuring the richness on all timesteps in a | ||
simulation is `N |> extinctions .|> parasite_richness`, or alternatively, | ||
`parasite_richness.(extinctions(N))`. In @fig:extinctions, we illustrate the | ||
output of this analysis on 100 simulations (average and standard deviation) for | ||
one of the networks. | ||
|
||
```@example ext | ||
N = web_of_life("A_HP_050") | ||
X = Float64[] | ||
Y = Float64[] | ||
for i in 1:200 | ||
timeseries = extinctions(N) | ||
path_l = parasite_richness.(timeseries)./richness(N; dims=1) | ||
prop_r = 1.0.-richness.(timeseries; dims=2)./richness(N; dims=2) | ||
append!(X, prop_r) | ||
append!(Y, path_l) | ||
end | ||
x = sort(unique(X)) | ||
y = zeros(Float64, length(x)) | ||
sy = zeros(Float64, length(x)) | ||
for (i, tx) in enumerate(x) | ||
y[i] = mean(Y[X.==tx]) | ||
sy[i] = std(Y[X.==tx]) | ||
end | ||
pl = plot(x, y, ribbon=sy, c=:black, fill=(:lightgrey), lw=2, ls=:dash, leg=false, margin = 10mm, grid=false, frame=:origin, xlim=(0,1), ylim=(0,1)) | ||
xaxis!(pl, "Proportion of hosts removed") | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
## Interaction imputation | ||
|
||
In the final example, we will apply the linear filtering method of @StocPois17 | ||
to suggest which negative interactions may have been missed in a network. | ||
Starting from a binary network, this approach generates a quantitative network, | ||
in which the weight of each interaction is the likelihood that it exists -- for | ||
interactions absent from the original network, this suggests that they may have | ||
been missed during sampling. This makes this approach interesting to guide | ||
empirical efforts during the notoriously difficult task of sampling ecological | ||
networks [@Jord16; @Jord16a]. | ||
|
||
In the approach of @StocPois17, the filtered interaction matrix (*i.e.* the | ||
network of weights) is given by | ||
|
||
\begin{equation} | ||
F_{ij} = \alpha_1Y_{ij} + \alpha_2\sum_k\frac{Y_{kj}}{n} + \alpha_3\sum_l\frac{Y_{il}}{m} + \alpha_4\frac{\sum Y}{n\times m} \,, | ||
\end{equation} | ||
|
||
where $\alpha$ is a vector of weights summing to 1, and $(n,m)$ is the size of | ||
the network. Note that the sums along rows and columns are actually the in and | ||
out degree of species. This is implemented in `EcologicalNetworks` as the | ||
`linearfilter` function. As in @StocPois17, we set all values in $\alpha$ to | ||
$1/4$. We can now use this function to get the top interaction that, although | ||
absent from the sampled network, is a strong candidate to exist based on the | ||
linear filtering output: | ||
|
||
```julia | ||
N = networks[50] | ||
F = linearfilter(N) | ||
``` | ||
|
||
We would like to separate the weights in 3: observed interactions, interactions | ||
that are not observed in this network but are observed in the metaweb, and | ||
interactions that are never observed. `EcologicalNetworks` has the | ||
`has_interaction` function to test this, but because `BinaryNetwork` are using | ||
Boolean values, we can look at the network directly: | ||
|
||
```julia | ||
scores_present = sort( | ||
filter(int -> N[int.from, int.to], interactions(F)), | ||
by = int -> int.probability, | ||
rev = true); | ||
|
||
scores_metaweb = sort( | ||
filter(int -> (!N[int.from,int.to])&(metaweb[int.from, int.to]), interactions(F)), | ||
by = int -> int.probability, | ||
rev = true); | ||
|
||
scores_absent = sort( | ||
filter(int -> !metaweb[int.from,int.to], interactions(F)), | ||
by = int -> int.probability, | ||
rev = true); | ||
``` | ||
|
||
The results of this analysis are presented in @fig:imputation: the weights | ||
$F_{ij}$ of interactions that are present locally ($Y_{ij}=\text{true}$) are | ||
*always* larger that the weight of interactions that are absent; furthermore, | ||
the weight of interactions that are absent locally are equal to the weight of | ||
interactions that are also absent globally, strongly suggesting that this | ||
network has been correctly sampled. | ||
|
||
```julia; echo=false | ||
nx, ny = range(0.0, stop=1.0, length=length(scores_present)), [x.probability for x in scores_present] | ||
pl = plot(nx, ny, grid=false, frame=:origin, lw=2, lab="Present locally", c=:black) | ||
nx, ny = range(0.0, stop=1.0, length=length(scores_metaweb)), [x.probability for x in scores_metaweb] | ||
plot!(pl, nx, ny, c=:black, lab="Present globally") | ||
nx, ny = range(0.0, stop=1.0, length=length(scores_absent)), [x.probability for x in scores_absent] | ||
plot!(pl, nx, ny, c=:darkgrey, ls=:dash, lab="Absent") | ||
xaxis!(pl, "Relative rank", (0,1)) | ||
yaxis!(pl, "Interaction weight", (0,1)) | ||
savefig("figures/imputation.pdf") | ||
``` | ||
|
||
![Relative weights (higher weights indicates a larger chance that the interaction has been missed when sampling) in one of the host-parasite networks according to the linear filter model of @StocPois17.](figures/imputation.pdf){#fig:imputation} |
Oops, something went wrong.
fb877e8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JuliaRegistrator register
fb877e8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Registration pull request created: JuliaRegistries/General/25397
After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.
This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via: