From 93037e5a7d291c32dd98dc57c1e526190155ed15 Mon Sep 17 00:00:00 2001 From: "Matthew J. Michalska-Smith" Date: Wed, 9 Feb 2022 20:46:00 -0500 Subject: [PATCH 01/12] :bug: fixed omnivory to use true trophic level and iterate across prey rather than predators --- src/foodwebs/omnivory.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/foodwebs/omnivory.jl b/src/foodwebs/omnivory.jl index 9f6ee28e1..cfe24b5e4 100644 --- a/src/foodwebs/omnivory.jl +++ b/src/foodwebs/omnivory.jl @@ -1,8 +1,8 @@ function omnivory(N::T) where {T <: UnipartiteNetwork} OI = Dict([s => 0.0 for s in species(N)]) - TL = fractional_trophic_level(N) - k = degree(N; dims=1) + TL = trophic_level(N) + k = degree_in(N) for sp_i in species(N) @@ -11,10 +11,10 @@ function omnivory(N::T) where {T <: UnipartiteNetwork} # For every species, we set its initial omnivory to 0 oi = 0.0 - for (j, sp_j) in enumerate(species(N)) + for sp_j in species(N) # Then for every species it consumes, we ha tl_diff = (TL[sp_j] - (TL[sp_i]-1.0)).^2.0 - corr = N[sp_i,sp_j]/k[sp_i] + corr = N[sp_j,sp_i]/k[sp_i] oi += tl_diff * corr end OI[sp_i] = oi From fe9f81feda011455a56d9e69c3cd4f34a84913e5 Mon Sep 17 00:00:00 2001 From: "Matthew J. Michalska-Smith" Date: Wed, 9 Feb 2022 20:49:28 -0500 Subject: [PATCH 02/12] :books: adding docstring for omnivory function including reference --- src/foodwebs/omnivory.jl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/foodwebs/omnivory.jl b/src/foodwebs/omnivory.jl index cfe24b5e4..43b291ba6 100644 --- a/src/foodwebs/omnivory.jl +++ b/src/foodwebs/omnivory.jl @@ -1,3 +1,16 @@ +""" + omnivory(N::T) where {T <: UnipartiteNetwork} + +Returns a vector of length |species(N)| with an index of consumption across +trophic levels. Note we explicitly assume that diet contribution is spread +evenly across prey species. + +#### References +- Christensen, Villy, and Daniel Pauly. "ECOPATH II—a software for balancing + steady-state ecosystem models and calculating network characteristics." + Ecological modelling 61, no. 3-4 (1992): 169-185. + +""" function omnivory(N::T) where {T <: UnipartiteNetwork} OI = Dict([s => 0.0 for s in species(N)]) From 88d87628155d397e3540b8f2b906fdc289e2c912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Poisot?= Date: Thu, 10 Feb 2022 21:42:37 -0500 Subject: [PATCH 03/12] update the documentation --- src/foodwebs/trophiclevels.jl | 75 ++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 19 deletions(-) diff --git a/src/foodwebs/trophiclevels.jl b/src/foodwebs/trophiclevels.jl index b3b23bbb1..b6d185fe0 100644 --- a/src/foodwebs/trophiclevels.jl +++ b/src/foodwebs/trophiclevels.jl @@ -1,24 +1,61 @@ -function fractional_trophic_level(N::T) where {T<:UnipartiteNetwork} - Y = nodiagonal(N) - producers = keys(filter(spedeg -> spedeg.second == 0, degree(Y; dims=1))) - sp = shortest_path(Y) - prod_id = findall(isequal(0), vec(sum(sp; dims=2))) - return Dict(zip(species(Y; dims=1), maximum(sp[:,prod_id]; dims=2).+1)) -end +""" + trophic_level(N::UnipartiteNetwork; f=maximum) + +Returns the trophic level (from Christensen & Pauly 1992) of every species +in the food web. Primary producers have a trophic level of 1, after that, +it's complicated (see *e.g.* Williams & Martinez 2004, Thompson et al. 2007). + +Post (2002) notes that the trophic level can be obtained from the maximum, +mean, or minimum distance to a producer. Given that consumers may be connected +to more than one producer, one might argue that the *mode* of this distribution +is also relevant. + +In favor of the minimum, one can argue that most energy transfer should happen +along short chains; but imagining a consumer atop a chain of length 5, also +connected directly to a producer, the minimum would give it a trophic level +of 2, hiding its position at the top of the food web. + +In favor of the maximum, one can argue that the higher chains give a better +idea of how far energy coming from the bottom of the food web can go. This +is a strong indication of how *vertically* diverse it is. +In this package, the keyword `f` defaults to `maximum`. Using any other +function, as long as it accepts an array (of chain distances) and return a +scalar, will work; `minimum` and `Statistics.mean` are natural alternatives, +as is `StatsBase.mode` or `Statistics.median`. +""" function trophic_level(N::T) where {T<:UnipartiteNetwork} - TL = fractional_trophic_level(N) - Y = nodiagonal(N) - D = zeros(Float64, size(Y)) - ko = degree_out(Y) - - # inner loop to avoid dealing with primary producers - for i in 1:richness(Y) - if ko[species(Y)[i]] > 0.0 - D[i,:] = Y[i,:]./ko[species(Y)[i]] + Y = nodiagonal(N) + producers = keys(filter(spedeg -> spedeg.second == 0, degree(Y; dims=1))) + sp = shortest_path(Y) + prod_id = findall(isequal(0), vec(sum(sp; dims=2))) + return Dict(zip(species(Y; dims=1), maximum(sp[:, prod_id]; dims=2) .+ 1)) +end + +""" + fractional_trophic_level(N::UnipartiteNetwork) + +Returns the *fractional* trophic level (after Odum & Heald 1975) +of species in a binary unipartite network. The trophic level is +calculated after Pauly & Christensen (1995), specifically as TLᵢ = 1 + +∑ⱼ(TLⱼ×DCᵢⱼ)/∑ⱼ(DCᵢⱼ), wherein TLᵢ is the trophic level +of species i, and DCᵢⱼ is the proportion of species j in the diet of +species i. Note that this function is calculated on a network where the +diagonal (i.e. self loops) are removed. +""" +function fractional_trophic_level(N::T) where {T<:UnipartiteNetwork} + TL = trophic_level(N) + Y = nodiagonal(N) + D = zeros(Float64, size(Y)) + ko = degree_out(Y) + + # inner loop to avoid dealing with primary producers + for i in 1:richness(Y) + if ko[species(Y)[i]] > 0.0 + D[i, :] = Y[i, :] ./ ko[species(Y)[i]] + end end - end - # return - return Dict(zip(species(N), 1 .+ D * [TL[s] for s in species(Y)])) + # return + return Dict(zip(species(N), 1 .+ D * [TL[s] for s in species(Y)])) end From 8b63ac9356a63bf86825bd1ea0b8796b7a341825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Poisot?= Date: Thu, 10 Feb 2022 23:04:03 -0500 Subject: [PATCH 04/12] new code for trophic levels --- src/foodwebs/trophiclevels.jl | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/foodwebs/trophiclevels.jl b/src/foodwebs/trophiclevels.jl index b6d185fe0..8c32a2972 100644 --- a/src/foodwebs/trophiclevels.jl +++ b/src/foodwebs/trophiclevels.jl @@ -23,17 +23,27 @@ In this package, the keyword `f` defaults to `maximum`. Using any other function, as long as it accepts an array (of chain distances) and return a scalar, will work; `minimum` and `Statistics.mean` are natural alternatives, as is `StatsBase.mode` or `Statistics.median`. + +The chain length from any species to any producer is taken as the shortest +possible path between these two species, as identified by the Dijkstra +algorithm. """ -function trophic_level(N::T) where {T<:UnipartiteNetwork} +function trophic_level(N::T; f=maximum) where {T<:UnipartiteNetwork} Y = nodiagonal(N) - producers = keys(filter(spedeg -> spedeg.second == 0, degree(Y; dims=1))) - sp = shortest_path(Y) - prod_id = findall(isequal(0), vec(sum(sp; dims=2))) - return Dict(zip(species(Y; dims=1), maximum(sp[:, prod_id]; dims=2) .+ 1)) + paths = dijkstra(Y) + consumers = collect(keys(filter(p -> iszero(p.second), degree(Y; dims=1)))) + filter!(int -> int.to ∈ consumers, paths) + tl = Dict{eltype(species(Y)),Float64}() + for sp in species(Y) + sp_paths = filter(int -> isequal(sp)(int.from), paths) + chain_lengths = [int.weight for int in sp_paths] + tl[sp] = isempty(chain_lengths) ? 1.0 : f(chain_lengths)+1.0 + end + return tl end """ - fractional_trophic_level(N::UnipartiteNetwork) + fractional_trophic_level(N::UnipartiteNetwork; kwargs...) Returns the *fractional* trophic level (after Odum & Heald 1975) of species in a binary unipartite network. The trophic level is @@ -42,9 +52,11 @@ calculated after Pauly & Christensen (1995), specifically as TLᵢ = 1 + of species i, and DCᵢⱼ is the proportion of species j in the diet of species i. Note that this function is calculated on a network where the diagonal (i.e. self loops) are removed. + +The keywords arguments are passed to `trophic_level`. """ -function fractional_trophic_level(N::T) where {T<:UnipartiteNetwork} - TL = trophic_level(N) +function fractional_trophic_level(N::T; kwargs...) where {T<:UnipartiteNetwork} + TL = trophic_level(N; kwargs...) Y = nodiagonal(N) D = zeros(Float64, size(Y)) ko = degree_out(Y) From 4da975df002d33e20c92c53a9b581b884beeddbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Poisot?= Date: Fri, 11 Feb 2022 09:39:51 -0500 Subject: [PATCH 05/12] patch release --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 194811487..d31fde164 100644 --- a/Project.toml +++ b/Project.toml @@ -2,7 +2,7 @@ name = "EcologicalNetworks" uuid = "f03a62fe-f8ab-5b77-a061-bb599b765229" authors = ["Timothée Poisot "] repo = "https://github.com/EcoJulia/EcologicalNetworks.jl" -version = "0.5.1" +version = "0.5.2" [deps] Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" From a28aab03dc016c4d0ba32bab23bcadfe7fed0fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Poisot?= Date: Fri, 11 Feb 2022 10:55:39 -0500 Subject: [PATCH 06/12] use a pseudo-inverse method for the fractional trophic level --- Project.toml | 1 + src/foodwebs/trophiclevels.jl | 33 ++++++++++++++++----------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Project.toml b/Project.toml index d31fde164..094879a6d 100644 --- a/Project.toml +++ b/Project.toml @@ -12,6 +12,7 @@ Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Requires = "ae029012-a4dd-5104-9daa-d747884805df" +Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" diff --git a/src/foodwebs/trophiclevels.jl b/src/foodwebs/trophiclevels.jl index 8c32a2972..fb2602528 100644 --- a/src/foodwebs/trophiclevels.jl +++ b/src/foodwebs/trophiclevels.jl @@ -37,7 +37,7 @@ function trophic_level(N::T; f=maximum) where {T<:UnipartiteNetwork} for sp in species(Y) sp_paths = filter(int -> isequal(sp)(int.from), paths) chain_lengths = [int.weight for int in sp_paths] - tl[sp] = isempty(chain_lengths) ? 1.0 : f(chain_lengths)+1.0 + tl[sp] = isempty(chain_lengths) ? 1.0 : f(chain_lengths) + 1.0 end return tl end @@ -53,21 +53,20 @@ of species i, and DCᵢⱼ is the proportion of species j in the diet of species i. Note that this function is calculated on a network where the diagonal (i.e. self loops) are removed. -The keywords arguments are passed to `trophic_level`. +This function uses a *pseudo*-inverse to solve the linear system described +above. """ -function fractional_trophic_level(N::T; kwargs...) where {T<:UnipartiteNetwork} - TL = trophic_level(N; kwargs...) - Y = nodiagonal(N) - D = zeros(Float64, size(Y)) - ko = degree_out(Y) - - # inner loop to avoid dealing with primary producers - for i in 1:richness(Y) - if ko[species(Y)[i]] > 0.0 - D[i, :] = Y[i, :] ./ ko[species(Y)[i]] - end - end - - # return - return Dict(zip(species(N), 1 .+ D * [TL[s] for s in species(Y)])) +function fractional_trophic_level(N::UnipartiteNetwork) + # Get the degree as a vector, ordered the same way as species + kout = EcologicalNetworks.degree_out(N) + 𝐤 = [kout[s] for s in species(N)] + # Adjacency matrix to solve the TL + 𝐀 = adjacency(N) + # Diet matrix + 𝐃 = .-(𝐀 ./ 𝐤) + replace!(𝐃, NaN => -0.0) + 𝐃[diagind(𝐃)] .= 1.0 .- 𝐃[diagind(𝐃)] + # Solve with the inverse matrix + 𝐛 = ones(eltype(𝐃), richness(N)) + return Dict(zip(species(N), pinv(𝐃) * 𝐛)) end From 178309ac214647e079108f203b1a3b16dfb06175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Poisot?= Date: Fri, 11 Feb 2022 12:06:49 -0500 Subject: [PATCH 07/12] fix omnivory and add doc --- docs/make.jl | 1 + docs/src/properties/foodwebs.md | 7 +++++ src/EcologicalNetworks.jl | 5 +-- src/foodwebs/omnivory.jl | 37 ---------------------- src/foodwebs/trophiclevels.jl | 55 +++++++++++++++++++++++++++------ test/community/foodwebs.jl | 12 +++---- 6 files changed, 60 insertions(+), 57 deletions(-) create mode 100644 docs/src/properties/foodwebs.md delete mode 100644 src/foodwebs/omnivory.jl diff --git a/docs/make.jl b/docs/make.jl index 035dfe2c3..e920f048f 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -31,6 +31,7 @@ makedocs( "Motifs" => "properties/motifs.md", "Centrality and paths" => "properties/paths.md", "Overlap and similarity" => "properties/overlap.md" + "Food web measures" => "properties/foodwebs.md" ], "Advanced information" => [ "Beta-diversity" => "properties/betadiversity.md", diff --git a/docs/src/properties/foodwebs.md b/docs/src/properties/foodwebs.md new file mode 100644 index 000000000..6bcf9b5d0 --- /dev/null +++ b/docs/src/properties/foodwebs.md @@ -0,0 +1,7 @@ +# Food web measures + +```@docs +distance_to_producer +trophic_level +omnivory +``` diff --git a/src/EcologicalNetworks.jl b/src/EcologicalNetworks.jl index f90e928d4..a25ea4e97 100644 --- a/src/EcologicalNetworks.jl +++ b/src/EcologicalNetworks.jl @@ -162,10 +162,7 @@ export KGL01, KGL02, KGL03, KGL04, KGL05, KGL06, KGL07, KGL08, KGL09, KGL10, # Food webs include(joinpath(".", "foodwebs/trophiclevels.jl")) -export fractional_trophic_level, trophic_level - -include(joinpath(".", "foodwebs/omnivory.jl")) -export omnivory +export distance_to_producer, trophic_level, omnivory include(joinpath(".", "information/entropy.jl")) export entropy, make_joint_distribution, mutual_information, conditional_entropy, diff --git a/src/foodwebs/omnivory.jl b/src/foodwebs/omnivory.jl deleted file mode 100644 index 43b291ba6..000000000 --- a/src/foodwebs/omnivory.jl +++ /dev/null @@ -1,37 +0,0 @@ -""" - omnivory(N::T) where {T <: UnipartiteNetwork} - -Returns a vector of length |species(N)| with an index of consumption across -trophic levels. Note we explicitly assume that diet contribution is spread -evenly across prey species. - -#### References -- Christensen, Villy, and Daniel Pauly. "ECOPATH II—a software for balancing - steady-state ecosystem models and calculating network characteristics." - Ecological modelling 61, no. 3-4 (1992): 169-185. - -""" -function omnivory(N::T) where {T <: UnipartiteNetwork} - OI = Dict([s => 0.0 for s in species(N)]) - - TL = trophic_level(N) - k = degree_in(N) - - for sp_i in species(N) - - # Species with no interaction have an omnivory index of 0 - k[sp_i] > 0 || continue - - # For every species, we set its initial omnivory to 0 - oi = 0.0 - for sp_j in species(N) - # Then for every species it consumes, we ha - tl_diff = (TL[sp_j] - (TL[sp_i]-1.0)).^2.0 - corr = N[sp_j,sp_i]/k[sp_i] - oi += tl_diff * corr - end - OI[sp_i] = oi - end - - return OI -end diff --git a/src/foodwebs/trophiclevels.jl b/src/foodwebs/trophiclevels.jl index fb2602528..3a7ecb739 100644 --- a/src/foodwebs/trophiclevels.jl +++ b/src/foodwebs/trophiclevels.jl @@ -1,9 +1,9 @@ """ - trophic_level(N::UnipartiteNetwork; f=maximum) + distance_to_producer(N::UnipartiteNetwork; f=maximum) -Returns the trophic level (from Christensen & Pauly 1992) of every species -in the food web. Primary producers have a trophic level of 1, after that, -it's complicated (see *e.g.* Williams & Martinez 2004, Thompson et al. 2007). +Returns the distance from a primary producert of every species in the food +web. Primary producers have a trophic level of 1, after that, it's complicated +(see *e.g.* Williams & Martinez 2004, Thompson et al. 2007). Post (2002) notes that the trophic level can be obtained from the maximum, mean, or minimum distance to a producer. Given that consumers may be connected @@ -28,7 +28,7 @@ The chain length from any species to any producer is taken as the shortest possible path between these two species, as identified by the Dijkstra algorithm. """ -function trophic_level(N::T; f=maximum) where {T<:UnipartiteNetwork} +function distance_to_producer(N::T; f=maximum) where {T<:UnipartiteNetwork} Y = nodiagonal(N) paths = dijkstra(Y) consumers = collect(keys(filter(p -> iszero(p.second), degree(Y; dims=1)))) @@ -43,7 +43,7 @@ function trophic_level(N::T; f=maximum) where {T<:UnipartiteNetwork} end """ - fractional_trophic_level(N::UnipartiteNetwork; kwargs...) + trophic_level(N::UnipartiteNetwork; kwargs...) Returns the *fractional* trophic level (after Odum & Heald 1975) of species in a binary unipartite network. The trophic level is @@ -53,10 +53,11 @@ of species i, and DCᵢⱼ is the proportion of species j in the diet of species i. Note that this function is calculated on a network where the diagonal (i.e. self loops) are removed. -This function uses a *pseudo*-inverse to solve the linear system described -above. +This function uses a *pseudo*-inverse to solve the linear system +described above *iff* the determinant of the diet matrix is 0 (it is +non-invertible). Otherwise, it will use an exact inverse. """ -function fractional_trophic_level(N::UnipartiteNetwork) +function trophic_level(N::UnipartiteNetwork) # Get the degree as a vector, ordered the same way as species kout = EcologicalNetworks.degree_out(N) 𝐤 = [kout[s] for s in species(N)] @@ -68,5 +69,39 @@ function fractional_trophic_level(N::UnipartiteNetwork) 𝐃[diagind(𝐃)] .= 1.0 .- 𝐃[diagind(𝐃)] # Solve with the inverse matrix 𝐛 = ones(eltype(𝐃), richness(N)) - return Dict(zip(species(N), pinv(𝐃) * 𝐛)) + invfunc = iszero(det(𝐃)) ? pinv : inv + return Dict(zip(species(N), invfunc(𝐃) * 𝐛)) +end + +""" + omnivory(N::T) where {T <: UnipartiteNetwork} + +Returns a vector of length richness(N) with an index of consumption across +trophic levels. Note we explicitly assume that diet contribution is spread +evenly across prey species, in proportion to their degree. Omnivory is +measured based on the output of `trophic_level`. + +#### References +- Christensen, Villy, and Daniel Pauly. "ECOPATH II—a software for balancing + steady-state ecosystem models and calculating network characteristics." + Ecological modelling 61, no. 3-4 (1992): 169-185. + +""" +function omnivory(N::T) where {T<:UnipartiteNetwork} + # Get the trophic level as an array + TL = trophic_level(N) + + # Prepare the omnivory index dictionary + OI = Dict(zip(species(N), fill(0.0, richness(N)))) + + # Loop + for sp in species(N) + if !isempty(N[sp,:]) + TLj = [TL[prey] for prey in N[sp,:]] + # Note that we don't need the normalisation here, because ∑Dᵢⱼ=1 + OI[sp] = sum((TLj .- mean(TLj)).^2.0) + end + end + + return OI end diff --git a/test/community/foodwebs.jl b/test/community/foodwebs.jl index f1f57f310..3b0d9b0ba 100644 --- a/test/community/foodwebs.jl +++ b/test/community/foodwebs.jl @@ -6,14 +6,14 @@ module TestFoodWebs s1 = unipartitemotifs()[:S1] s1_ftl = fractional_trophic_level(s1) s1_tl = trophic_level(s1) - @test maximum(values(s1_ftl)) == 3 - @test maximum(values(s1_tl)) == 3.0 - @test s1_ftl[:a] == 3 - @test s1_ftl[:b] == 2 - @test s1_ftl[:c] == 1 + @test maximum(values(s1_ftl)) ≈ 3 + @test maximum(values(s1_tl)) ≈ 3.0 + @test s1_ftl[:a] ≈ 3 + @test s1_ftl[:b] ≈ 2 + @test s1_ftl[:c] ≈ 1 s2 = unipartitemotifs()[:S2] - @test minimum(values(fractional_trophic_level(s1))) == 1.0 + @test minimum(values(fractional_trophic_level(s1))) ≈ 1.0 @test minimum(values(trophic_level(s1))) == 1.0 # test on a quantitative bipartite network From 86ad20a5e7b6c105feb71c064be4aa6217ba645b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Poisot?= Date: Fri, 11 Feb 2022 12:21:23 -0500 Subject: [PATCH 08/12] test fix --- test/community/foodwebs.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/community/foodwebs.jl b/test/community/foodwebs.jl index 3b0d9b0ba..6e789ec27 100644 --- a/test/community/foodwebs.jl +++ b/test/community/foodwebs.jl @@ -4,8 +4,8 @@ module TestFoodWebs # test trophic levels on motifs s1 = unipartitemotifs()[:S1] - s1_ftl = fractional_trophic_level(s1) - s1_tl = trophic_level(s1) + s1_ftl = trophic_level(s1) + s1_tl = distance_to_producer(s1) @test maximum(values(s1_ftl)) ≈ 3 @test maximum(values(s1_tl)) ≈ 3.0 @test s1_ftl[:a] ≈ 3 @@ -13,8 +13,8 @@ module TestFoodWebs @test s1_ftl[:c] ≈ 1 s2 = unipartitemotifs()[:S2] - @test minimum(values(fractional_trophic_level(s1))) ≈ 1.0 - @test minimum(values(trophic_level(s1))) == 1.0 + @test minimum(values(trophic_level(s1))) ≈ 1.0 + @test minimum(values(distance_to_producer(s1))) == 1.0 # test on a quantitative bipartite network @test web_of_life("A_HP_002") |> From 6a48cc8ae1d30ef0283a570af11871dc9a159066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Poisot?= Date: Fri, 11 Feb 2022 12:21:30 -0500 Subject: [PATCH 09/12] drop Revise --- Project.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Project.toml b/Project.toml index 094879a6d..d31fde164 100644 --- a/Project.toml +++ b/Project.toml @@ -12,7 +12,6 @@ Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Requires = "ae029012-a4dd-5104-9daa-d747884805df" -Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" From 6cab51ac8e92565654ce2902e5cc039e9626b6d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Poisot?= Date: Fri, 11 Feb 2022 12:50:53 -0500 Subject: [PATCH 10/12] remove un-required test --- test/community/foodwebs.jl | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/community/foodwebs.jl b/test/community/foodwebs.jl index 6e789ec27..dd511510c 100644 --- a/test/community/foodwebs.jl +++ b/test/community/foodwebs.jl @@ -16,12 +16,4 @@ module TestFoodWebs @test minimum(values(trophic_level(s1))) ≈ 1.0 @test minimum(values(distance_to_producer(s1))) == 1.0 - # test on a quantitative bipartite network - @test web_of_life("A_HP_002") |> - x -> convert(BinaryNetwork, x) |> x -> convert(UnipartiteNetwork, x) |> - trophic_level |> values |> minimum |> x -> x == 1.0 - @test web_of_life("A_HP_002") |> - x -> convert(BinaryNetwork, x) |> x -> convert(UnipartiteNetwork, x) |> - trophic_level |> values |> maximum |> x -> x == 2.0 - end From 7c8c615df8fd1ead15456fa28bbc801dbbf5d041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Poisot?= Date: Fri, 11 Feb 2022 12:51:48 -0500 Subject: [PATCH 11/12] doc index fix --- docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index e920f048f..0906e2b85 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -30,7 +30,7 @@ makedocs( "Nestedness" => "properties/nestedness.md", "Motifs" => "properties/motifs.md", "Centrality and paths" => "properties/paths.md", - "Overlap and similarity" => "properties/overlap.md" + "Overlap and similarity" => "properties/overlap.md", "Food web measures" => "properties/foodwebs.md" ], "Advanced information" => [ From 478cd2d698d8945b2438d755f0869608f7a531e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Poisot?= Date: Fri, 11 Feb 2022 14:01:49 -0500 Subject: [PATCH 12/12] fix the omnivory test --- test/community/foodwebs.jl | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/test/community/foodwebs.jl b/test/community/foodwebs.jl index dd511510c..836e0783d 100644 --- a/test/community/foodwebs.jl +++ b/test/community/foodwebs.jl @@ -1,19 +1,26 @@ module TestFoodWebs - using Test - using EcologicalNetworks +using Test +using EcologicalNetworks - # test trophic levels on motifs - s1 = unipartitemotifs()[:S1] - s1_ftl = trophic_level(s1) - s1_tl = distance_to_producer(s1) - @test maximum(values(s1_ftl)) ≈ 3 - @test maximum(values(s1_tl)) ≈ 3.0 - @test s1_ftl[:a] ≈ 3 - @test s1_ftl[:b] ≈ 2 - @test s1_ftl[:c] ≈ 1 +# test trophic levels on motifs +s1 = unipartitemotifs()[:S1] +s1_ftl = trophic_level(s1) +s1_tl = distance_to_producer(s1) +@test maximum(values(s1_ftl)) ≈ 3 +@test maximum(values(s1_tl)) ≈ 3.0 +@test s1_ftl[:a] ≈ 3 +@test s1_ftl[:b] ≈ 2 +@test s1_ftl[:c] ≈ 1 - s2 = unipartitemotifs()[:S2] - @test minimum(values(trophic_level(s1))) ≈ 1.0 - @test minimum(values(distance_to_producer(s1))) == 1.0 +s2 = unipartitemotifs()[:S2] +@test minimum(values(trophic_level(s1))) ≈ 1.0 +@test minimum(values(distance_to_producer(s1))) == 1.0 + +# Test for omnivory +for s in species(s1) + if iszero(EcologicalNetworks.degree_out(s1)[s]) + @test iszero(omnivory(s1)[s]) + end +end end