using DataFrames, Plots, Random, Distributions
using EcologicalNetworksDynamics
In the previous chapter, we learned how to make networks and run a simulation. We did this for a simple tri-trophic chain where we specified the network with a matrix of ones and zeros, and for a more complex network defined by the niche model where we specified species richness and connectance. We also learned how to visualise the simulations and to collect several metrics about the simulations, including detail on biomass, diversity and stability.
In this tutorial, we are going to learn how to do experiments. We’ll learn first how to generate multiple networks and collect information on how network structure impacts our metrics. Then we’ll learn how to manipulate parameters in the model, again collecting information on how variation in these parameters impacts our metrics.
For example, we might be interested in how species richness or connectance impacts biomass and stability. Or how the carrying capacity of the producers impacts biomass and stability of the community (e.g. bottom up processes). We’ll look at both of these.
Getting Setup
As with our previous exercises, we need to have a few packages that allow making networks, simulating them and collecting the data
Your (re)introduction to loops: making multiple networks example
One of the tricks to doing experiments is learning how to run a loop. Julia is super-fast with running loops. This is a bit different to R, which has a bad rep for loops. It’s not terrible. But Julia is built to do loops fast.
What we will do here is build a simple loop that makes 3 networks, each with a different species richness, but the same connectance.
Note here that we introduce the use of the argument tol_C
. Because the niche model
produces networks based on probability theory (it uses the beta-distribution), the connectance we ask for is not always the connectance we get. The tol_C
argument ensure that connectance is within a tolerance range - in this case, having asked for C = 0.2
and a tol_C = 0.01
we will get 0.19 < C < 2.01
. This is like embedding a while loop within the FoodWeb
function! We note too that the function nichemodel
can take a value of L
instead of C
, and there is an associated tol_L
argument for this choice too.
Random.seed!(12325) # ensures your network and this one are the same
= [10,20,30] # define the number of species
S = 0.2 # define the connectance (complexity) of the network
C
# collection zone for the networks
= []
nets
# construct the food webs
# we loop over the 3 values of S
# we use push!() to add the food webs to nets
# always start with a for and end with an end.
for i in 1:3
push!(nets, Foodweb(:niche; S = S[i], C = C))
end
Great. Let’s see if we got what we expected in nets.
nets
3-element Vector{Any}:
blueprint for Foodweb with 22 trophic links
blueprint for Foodweb with 81 trophic links
blueprint for Foodweb with 182 trophic links
Magnificent, we have three networs and that’s a win. We also see that they are each for a different and appropriate S. Win no. 2. We can actually now check to see what the connectances actually are. Again, we’ll use a loop, println
and introduce you to the details of the FoodWeb
object.
First, let’s look at one of the networks.
1] nets[
blueprint for Foodweb with 22 trophic links:
A: 10×10 SparseArrays.SparseMatrixCSC{Bool, Int64} with 22 stored entries:
⋅ 1 1 1 1 1 1 1 1 1
⋅ 1 1 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅
⋅ ⋅ ⋅ ⋅ 1 1 1 1 ⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1 1
⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1 ⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅ 1 1 1 ⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1
⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅
We can see that the A
element is the matrix and you can guess that the M
is the body M
asses. We also find tha there are 3 producers and 7 invertebrates and it is derived from the niche model
A side note on the metabolic classes. The default parametrisation, and nearly all of the published work with the BEFW, uses invertebrates for all the non-producer species. It is possible to include others. But the data, currently, are not helpful (low volume) in supporting robust inference with these types of species.
Now, recall that we can look specifically at the matrix by using nets[1].A
which grabs the A
part. We introduce here the function sum
. As in R, sum()
does what it says on the tin: for a vector, it addes up all the numbers and for a matrix, it does the same! In our case here, when sum()
is applied to a matrix of ones and zeros, it counts all the 1’s…. thus is the estimate of the number of links in the community.
Finally, we note (again?) that size
applied to the network returns two numbers - the number of rows and the number of columns. For our networks, the matrix is square. So grabbing one of these (rows = [1]) and squaring it delivers our ‘potential number of links’ (e.g. \(species^2\)).
We can put that all together here to define connectance as \(Con = links/S^2\). Do be careful to watch where you put the various []
’s. One of them is about the index (i.e. [i]
) and the other is about the dimension ([1]
) of the matrix.
for i in 1:3
println(sum(nets[i].A)/size(nets[i].A)[1]^2)
end
0.22
0.2025
0.20222222222222222
Different ways to run loops.
There is another way to make this set of networks. Here we use a while
loop to create 3 networks with the same species richness and connectance. We might need to do this to generate replicates. This is a good exercise with the niche model as it reminds you that it is a probabilistic tool… you can get several networks with the same S and C, but the links will be in slightly different places.
while
loops work on conditions… for example, if we want three networks, we could ask that the loop keep working to make the networks until we have three. To do this, we need a monitoring variable that lets us assess where we are against our target.
Lets see how to do that.
# how many replicates do we want?
= 3
reps
begin
# list to store networks
global networks = []
# monitoring variable l (the letter l)
global l = length(networks)
# while loop
while l < reps # reps is 3 here...
# generate a network
= Foodweb(:niche; S = 20, C = 0.15)
A # add the network to the set
push!(networks, A)
# update the monitor
global l = length(networks)
end
end
The term global
means that the obects are made available in our global environment and should be there for us to see. If you look closely at the mini-matrices, you’ll see they are all different in micro-structure, despite having the same number of links and the same connectance.
The presentation of the matrix is very specific here… the rows correspond to the predators and the columns the resources. Obstensibly, the ranking is by body size, so small things are at the upper left. This view shows that big things tend to eat small and big things, while small things eat small. Historically, the reflection (pivot around the diagnol) has also been used, where the predators are the columns and the resources the rows. This lead to a ‘feature’ of real and theoretical networks aligning, call upper triangularity
. In this latter presentation, most of the links would be in the upper triangle. In the current presentation, the links are in the lower triangle. So we can just call the feature triangularity
. The niche model reproduces this triangularity.
networks
3-element Vector{Any}:
blueprint for Foodweb with 55 trophic links
blueprint for Foodweb with 63 trophic links
blueprint for Foodweb with 62 trophic links
1].A networks[
20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 55 stored entries:
⎡⠉⠉⠉⣉⡡⠐⠒⠒⠒⠂⎤
⎢⠀⠀⠀⠀⠀⠔⠒⠒⠒⠂⎥
⎢⠀⠀⠀⠀⠨⠕⠒⠒⠒⠂⎥
⎢⠀⠀⠀⠀⠀⠀⠐⠒⠿⡅⎥
⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⎦
2].A networks[
20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 63 stored entries:
⎡⠉⠩⠭⠉⠉⠁⠀⠀⠀⠒⎤
⎢⠀⠀⠈⠒⣒⠒⠒⠶⠤⠀⎥
⎢⠀⠀⠀⠀⠒⠀⠨⣭⣭⡤⎥
⎢⠀⠀⠀⠀⠀⠀⠀⠤⠤⠉⎥
⎣⠀⠀⠀⠀⠀⠀⠀⠀⠐⠛⎦
3].A networks[
20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 62 stored entries:
⎡⣀⣭⣭⣍⣉⣉⡉⠉⠁⠀⎤
⎢⠀⠀⠀⠉⠉⠁⢠⠤⠤⠤⎥
⎢⠀⠀⠀⠀⠀⠉⢰⣶⠀⠀⎥
⎢⠀⠀⠀⠀⠀⠀⠈⠉⡀⠀⎥
⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⎦
Linking the networks to the Ecological Networks Dynamics
Fantastic. Now you are ready for the next steps. We want to run the EcologicalNetworksDynamics
model on each of these networks. Furthermore, we want to collect the biomass and stability information for all three into a data frame. Let’s see how we do that.
Step 1: Create the collecting data frame
First, we create the holding pen for our information. We’ll construct a data frame to collect five pieces of information: the network id (1,2 or 3), species richness at the start (our initial S), species richness at the end, total biomass at the end and stability at the end.
= DataFrame(Network = [], Init_Rich = [], Fin_Rich = [], Tot_biomass = [], Shannon_dic = []) outputs
Row | Network | Init_Rich | Fin_Rich | Tot_biomass | Shannon_dic |
---|---|---|---|---|---|
Any | Any | Any | Any | Any |
Step 2: use the pre-defined networks
We can use our nets
object from above now. Each of these networks has a different species richness.
for i in 1:3
# prep: define size of network
= size(nets[i].A)[1]
S
# deliver some progress reporting
println("\nThis is network: ", i, "with species richness = ", S,"\n")
# step A: define model paramters
= default_model(nets[i])
params
# step B: define body mass
= rand(S)
B0
# step C: set number of timestamps
= 300
t
# step D: simulate
= simulate(params, B0, t)
out
# steps D: calculate metrics
= richness(out)
fin_rich = total_biomass(out)
fin_biomass = shannon_diversity(out)
s_div
# step E: add things to the data frame
# note the first arg is the data frame and then
# the values we want allocated to the five slots
# are in []
push!(outputs, [i, S, fin_rich, fin_biomass, s_div])
end
This is network: 1with species richness = 10
This is network: 2with species richness = 20
This is network: 3with species richness = 30
Amazing. Let’s see if what we wanted collected has ended up in our data frame. Wonderful! Splendiferous. Fantabulous.
println(outputs)
3×5 DataFrame
Row │ Network Init_Rich Fin_Rich Tot_biomass Shannon_dic
│ Any Any Any Any Any
─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ 1 10 [10, 10, 10, 10, 10, 10, 10, 10,… [4.70537, 4.63199, 4.53209, 4.42… [8.375, 8.40912, 8.44306, 8.4699…
2 │ 2 20 [20, 20, 20, 20, 20, 20, 20, 20,… [8.52201, 8.4081, 8.26162, 8.102… [15.0407, 15.0769, 15.1077, 15.1…
3 │ 3 30 [30, 30, 30, 30, 30, 30, 30, 30,… [14.7649, 14.5082, 14.2062, 13.8… [24.3797, 24.4948, 24.5777, 24.6…
Dissecting more from simulate
Note the details on extinctions that comes from a model run. For example, let’s revisit our sim_niche
object (you won’t necessarily have to re-run this if you are working in one big script)
= 20; # define the number of species
S = 0.2; # define the connectance (complexity) of the network
C
# construct the food web
Random.seed!(12325) # ensures your network and this one are the same
= Foodweb(:niche; S = S, C = C)
foodweb_niche
# construct the equations and fixed parameters
= default_model(foodweb_niche)
params_niche
# define bodymasses between 0 and 1 and get S = 20 of them.
Random.seed!(123)
= rand(S)
B0
# simulate using params and bodymasses
# specify number of time steps
= 300
t = simulate(params_niche, B0, t) sim_niche
retcode: Success
Interpolation: 3rd order Hermite
t: 51-element Vector{Float64}:
0.0
0.0983252574499891
0.28544083243480267
0.5267982237043161
0.8245753364604138
1.181896742988936
1.6418353914084878
2.203829100924959
2.893464061893281
3.729699102007749
4.728753111889612
5.890702747756841
7.2218772360496395
⋮
136.70283821576533
145.48441982502288
155.57070934467725
166.67876410920994
179.5612866567586
193.9800038364207
210.21105297520486
227.83156289127072
247.0838336915681
267.94281052881126
290.8959793077713
300.0
u: 51-element Vector{Vector{Float64}}:
[0.906299638797481, 0.44349373245960455, 0.7456733811393941, 0.5120830400366143, 0.2538490889415096, 0.33415153638191886, 0.4273278808735992, 0.867547200255958, 0.09913361484360417, 0.12528740769155033, 0.6922086620547391, 0.13655147513745736, 0.03209667335274724, 0.3505458214588266, 0.9303323763821093, 0.9594335994071538, 0.5819123423876457, 0.3114475007050529, 0.12114752051812694, 0.20452981732035946]
[0.9169483131714715, 0.444402194534041, 0.7667640455857161, 0.5179071161683636, 0.25596644376248334, 0.3439614083570855, 0.42881389580038637, 0.8404857181508336, 0.10207349613818459, 0.12980979255930417, 0.7045585608788062, 0.14142469702894178, 0.033700254458592344, 0.35322775442579823, 0.9254383246584946, 0.8428424981719224, 0.5353929049386887, 0.2716712297929136, 0.11790964375471776, 0.20588623005171253]
[0.9372189186622565, 0.446138581295766, 0.8030805319662981, 0.5280429096670912, 0.25960285298532004, 0.36088969827160805, 0.43143000229873113, 0.7941678141517742, 0.107334065965393, 0.13803877097876832, 0.7224846396419364, 0.150274714852675, 0.03655779055568964, 0.35202356186576755, 0.8867871855452475, 0.6561325211685619, 0.45370991951901846, 0.21879863147029777, 0.1144327890249893, 0.21137607850479412]
[0.963419944890434, 0.4478457678502066, 0.8407656301021255, 0.5394619505769526, 0.26358620538619504, 0.3785307293750754, 0.43443524658702654, 0.7426580903726461, 0.11338938338304744, 0.1475698891121404, 0.7345099631141349, 0.16048747662896795, 0.03959434344670769, 0.3379755377009729, 0.7958692645000881, 0.48283669535781387, 0.36706195693003885, 0.17548000193294144, 0.1136592394878268, 0.22309854306314952]
[0.995616193064571, 0.44805738727466143, 0.8700643195894429, 0.5512240918443782, 0.2674989824178032, 0.3924051349926597, 0.4375425793363201, 0.6886449125246876, 0.11960335804730916, 0.15695502649258633, 0.7327878032629778, 0.17047486846995694, 0.0420936774665965, 0.3062032871443506, 0.6610340292426684, 0.34855000462048347, 0.2881369319293169, 0.14175624955652485, 0.11666389844136492, 0.24243967254676815]
[1.0331366869886944, 0.44448629343725343, 0.8788288901686566, 0.5620901047900512, 0.2708572048035862, 0.39695429480179645, 0.44018298027640984, 0.6333401253753693, 0.1252037789780579, 0.1640984843116221, 0.7114983769875807, 0.17795514254857084, 0.04354809380952039, 0.26092610308891634, 0.5154058541922188, 0.25624511921879434, 0.22330145420147088, 0.11586948470233616, 0.12436895504970236, 0.26962910331924905]
[1.0773089982155897, 0.43396923698721435, 0.8556572961992899, 0.5707904139404543, 0.2731983214483226, 0.38705755776238965, 0.4413794083264426, 0.57197930814629, 0.12978003467017415, 0.16724868374246712, 0.6675169557355778, 0.18101017312972054, 0.04388752925907648, 0.20909394578211202, 0.3805309865842198, 0.19230727005942244, 0.16943175281775166, 0.09443672996682428, 0.13906102138589269, 0.30741066949967055]
[1.1213743703927337, 0.4149870885160012, 0.7975741540831984, 0.5733620864984142, 0.2733077885606147, 0.36141676843558873, 0.4391552288251882, 0.5071960218562799, 0.13225598133704913, 0.1649144766546638, 0.6093837906327526, 0.17807037605762552, 0.04315159765633695, 0.1631734536430942, 0.2790930366914647, 0.15237925689592774, 0.12890880773111002, 0.0777317468581009, 0.16225155189984958, 0.35425475261372863]
[1.1573410183305781, 0.3875799067335869, 0.7122633234623346, 0.5656661531044221, 0.2699342224158771, 0.32362037390928877, 0.43151833519945715, 0.43980122366299085, 0.1320832740044849, 0.15754833392958092, 0.5485937790090555, 0.16967851768901068, 0.04155688582593655, 0.12670961646818607, 0.20790093579654878, 0.12919220653556573, 0.09920527144448085, 0.06511083602693121, 0.1957265685332169, 0.40863184877785175]
[1.1744909386178761, 0.35353525150930704, 0.6130415990319116, 0.5442924204781258, 0.2619765432579562, 0.2797239154423789, 0.41725964546931765, 0.3734718885747243, 0.12906194711831975, 0.14648620822639452, 0.49617455885534983, 0.15734180901650238, 0.039351964038387546, 0.0993990767009241, 0.15977668195469585, 0.1193453433823383, 0.07853078787521317, 0.05684848395648957, 0.23880211323157663, 0.46473430625333423]
[1.1636651009007108, 0.3155425241026375, 0.5129043599973696, 0.5086210124289895, 0.24908969960788688, 0.23553191470443982, 0.3966456636545259, 0.3124900352369809, 0.12355869405172261, 0.13330212010711523, 0.45885425946835634, 0.14280589051662543, 0.036833828434965285, 0.07940681588029759, 0.1280065867800307, 0.12159259236413968, 0.06534238144397321, 0.053601952458352684, 0.28528412637082984, 0.5126103913127859]
[1.1215900120487023, 0.2768216752264026, 0.42206636648520485, 0.46189135063482056, 0.23215126320140814, 0.19551978933588599, 0.37144587200796514, 0.26042387609908113, 0.11647562742120145, 0.11955373899209087, 0.4381554894529827, 0.1277697315605396, 0.034397853577932694, 0.06512710102028911, 0.10768752758342186, 0.13551750917697, 0.058102384679568894, 0.055907692857973916, 0.3220846544335181, 0.5412432565515389]
[1.051674472438156, 0.2396400556460993, 0.34499392466732914, 0.408962875223587, 0.21264909765819076, 0.16158429863184295, 0.3435589630316772, 0.2180232510648064, 0.10878792457246415, 0.10632571872188118, 0.43013574616355804, 0.11339063974249527, 0.03248700163555598, 0.055268908325187105, 0.0946316891444375, 0.1595784203240174, 0.05459709129704919, 0.0631635952778267, 0.33753068620574334, 0.5455404467088186]
⋮
[0.00032755644980272486, 0.00042642730013303957, 0.00024189593390109746, 3.1111688980955344e-5, 0.002186365444974394, 0.0001284836050334962, 0.009392611128074742, 0.2289263661082618, 0.027817843518977224, 0.00011632790937708126, 0.4448717546882417, 0.0001223774188672115, 0.198564855194196, 0.09669339044487263, 0.041438780171243736, 0.21624377256231636, 0.010260398961170272, 0.1106446052574405, 0.30895191650548376, 0.48344362584850714]
[0.0001996798247022266, 0.0003009378761392906, 0.00015346749983007282, 1.8190449427202614e-5, 0.0017884347223449826, 8.151473534424173e-5, 0.0077101296606787864, 0.23181199431785626, 0.025313811373776522, 7.379449257908107e-5, 0.44476144744230767, 7.763164111187508e-5, 0.19771575290544488, 0.0981753484444294, 0.0415237986113816, 0.21618611797874981, 0.010096001729578499, 0.1107711243020971, 0.3089588621965838, 0.4835526097023227]
[0.00011328126257715799, 0.0002025145740727682, 9.102676275323986e-5, 9.86615934389697e-6, 0.0014273867429624918, 4.834918126253599e-5, 0.006152674701416408, 0.2345821350465174, 0.022777702555973164, 4.3766536607882777e-5, 0.44485825775398713, 4.604210489119089e-5, 0.19677603845677671, 0.0996135511824476, 0.04163063947534051, 0.21611456663905765, 0.00992313898370846, 0.1108762739174712, 0.30896257460215903, 0.4836121681503955]
[6.07969185813491e-5, 0.00013150891522278353, 5.122984902532575e-5, 5.0559263528295375e-6, 0.0011197509119850043, 2.721092248119792e-5, 0.004805123705498752, 0.2371493862104039, 0.02034698607033935, 2.4630532478594332e-5, 0.44507776580317365, 2.591108561516969e-5, 0.19582059389086015, 0.10090484291104647, 0.04175110898630074, 0.21605866945798072, 0.009748297718843965, 0.1109547748500005, 0.308965762906422, 0.48361873148098766]
[2.9540113221979872e-5, 8.00347447973086e-5, 2.6268553079549285e-5, 2.3358462951272875e-6, 0.0008502538978690424, 1.3952641028662382e-5, 0.0036125895986525765, 0.23963412412998863, 0.017924696653654346, 1.2629101514971793e-5, 0.4453417610345992, 1.3285671319358326e-5, 0.19486664345382582, 0.10209874101875081, 0.041891604062307145, 0.2160237975426658, 0.00956208380761516, 0.11101835580249045, 0.3089707135225891, 0.48359145640506035]
[1.3166616427449579e-5, 4.60961582614326e-5, 1.241859399595492e-5, 9.875013357564836e-7, 0.0006289434801525733, 6.596183545884943e-6, 0.0026293723865516917, 0.24190491545204867, 0.015626334170708748, 5.970359692556319e-6, 0.44560575498650923, 6.280744324641365e-6, 0.19400924653479448, 0.10314206416955765, 0.04204857588531362, 0.2160007866180423, 0.009371522869382096, 0.11107366457263641, 0.3089769794039354, 0.48355133078668755]
[5.288582093742206e-6, 2.4853056623534485e-5, 5.32431964558186e-6, 3.7495755123700837e-7, 0.0004510237192764804, 2.8280327624688987e-6, 0.0018418173438047715, 0.24395924306889033, 0.013458321791607284, 2.559692577943294e-6, 0.44587256631997335, 2.692763414898462e-6, 0.19326957086896235, 0.10403490013949204, 0.04222157762263886, 0.21597907364688387, 0.009176377022194124, 0.11112583015368675, 0.30898347361961076, 0.4835073952384332]
[1.960571333984018e-6, 1.2748386630159753e-5, 2.115911956181734e-6, 1.3122771778296083e-7, 0.00031649230625780636, 1.1238747466059242e-6, 0.0012535673852407435, 0.2457433105385709, 0.011504652249667801, 1.0172301703560636e-6, 0.44612733302168156, 1.0701126911743665e-6, 0.19267165202271308, 0.1047507539103007, 0.04240100704365944, 0.21595925499391128, 0.008984468602875842, 0.11117426849212075, 0.30898978378818076, 0.48346305093339226]
[6.595296475377276e-7, 6.157495485353746e-6, 7.673573735587585e-7, 4.1573174269355544e-8, 0.0002163095240186386, 4.0758481170993133e-7, 0.0008246351715236552, 0.24730063052972948, 0.009744807150823888, 3.6890828571649465e-7, 0.4463589658982419, 3.880865976484553e-7, 0.19219749029253488, 0.10531819548561512, 0.042584771757986466, 0.21594251593637606, 0.008795235529894242, 0.11122083597743129, 0.3089962400343031, 0.48342085434013]
[2.0108052810226762e-7, 2.8004575219465937e-6, 2.5369560293790977e-7, 1.190656631256341e-8, 0.00014408987057401768, 1.3475139250220505e-7, 0.0005246117248146955, 0.24864251960077316, 0.008183727277329841, 1.2196446538994685e-7, 0.4465625705694917, 1.2830498581813105e-7, 0.19183327165148306, 0.10575941597710509, 0.04276848561656389, 0.21592768854223388, 0.008611086962690943, 0.11126649455166937, 0.30900276016604544, 0.4833835692529364]
[5.35850498787597e-8, 1.174593201709331e-6, 7.398752912499898e-8, 2.965192061208363e-9, 9.266705935747393e-5, 3.929875986723788e-8, 0.00031929137827090367, 0.24981133030734196, 0.006788855740405869, 3.556958190340493e-8, 0.4467437607797747, 3.7418723667047955e-8, 0.19155285868338037, 0.10610455981258715, 0.04295191471606665, 0.21591384077514106, 0.008430160333184566, 0.1113122756892104, 0.30900934087551246, 0.48335082223348647]
[3.2821854904203205e-8, 8.406671643638472e-7, 4.6640508998017896e-8, 1.7793663607263053e-9, 7.799523091116062e-5, 2.4773285240091262e-8, 0.0002627973314424048, 0.2502039748903548, 0.00631276636245039, 2.2422472598477954e-8, 0.4468055436036614, 2.358814075481337e-8, 0.19146688286657296, 0.10621159455428622, 0.04301932407939025, 0.21590899888568155, 0.008364030293673712, 0.11132929056683419, 0.3090117977250657, 0.4833397504740079]
We’ve constructed a helper function to get information on which species go extinct and when they do.
Section is no longer a built-in functionality in END. Alain should be able to address
# collect and organise extinctions
= get_extinct_species(sim_niche) extinctions
This is a Dict
object. The numbers on the left of the =>
are known as the keys
and the numbers on the right are values
. We can create a mini- data frame out of this with the following code. key
and values
are actually extractor functions and collect
is translating the extracted information into a vector.
# create a data frame of extinctions
= DataFrame(who = collect(keys(extinctions)), when = collect(values(extinctions))) ee1
Now we can try and add this information to the plot. For the time being, we’ll focus on adding the times that each of these species goes extinct to our figure. To do this we need to access the extinction time column (when
), add a bit of noise/jitter so that times that are really close together can be seen on our x-axis, and then plot these as points with coordinates x = when
and y = 0
.
# add some jitter for close together events
= ee1[:,2] .+rand.()
exts
# plot
plot(sim_niche)
# add jittered extinction events.
plot!(exts, zeros(size(ee1[:,1])), seriestype = :scatter, legend = false)
Pretty cool!
What’s next
In the next chapter, you’ll be creating larger experiments with loops over actual parameters in the model, including the predator-prey size ratio, values of carry capacity and the predator-prey size ratio.