Author

Danet and Becks, based on originals by Delmas and Griffiths

Published

November 14, 2024

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

using DataFrames, Plots, Random, Distributions
using EcologicalNetworksDynamics

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

S = [10,20,30] # define the number of species
C = 0.2 # define the connectance (complexity) of the network

# 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.

nets[1]
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 Masses. We also find tha there are 3 producers and 7 invertebrates and it is derived from the niche model

Tip

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?
reps = 3

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
        A = Foodweb(:niche; S = 20, C = 0.15)
        # 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.

Note

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
networks[1].A
20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 55 stored entries:
⎡⠉⠉⠉⣉⡡⠐⠒⠒⠒⠂⎤
⎢⠀⠀⠀⠀⠀⠔⠒⠒⠒⠂⎥
⎢⠀⠀⠀⠀⠨⠕⠒⠒⠒⠂⎥
⎢⠀⠀⠀⠀⠀⠀⠐⠒⠿⡅⎥
⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⎦
networks[2].A
20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 63 stored entries:
⎡⠉⠩⠭⠉⠉⠁⠀⠀⠀⠒⎤
⎢⠀⠀⠈⠒⣒⠒⠒⠶⠤⠀⎥
⎢⠀⠀⠀⠀⠒⠀⠨⣭⣭⡤⎥
⎢⠀⠀⠀⠀⠀⠀⠀⠤⠤⠉⎥
⎣⠀⠀⠀⠀⠀⠀⠀⠀⠐⠛⎦
networks[3].A
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.

outputs = DataFrame(Network = [], Init_Rich = [], Fin_Rich = [], Tot_biomass = [], Shannon_dic = [])
0×5 DataFrame
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
    S = size(nets[i].A)[1]

    # deliver some progress reporting
    println("\nThis is network: ", i, "with species richness = ", S,"\n")

    # step A: define model paramters
    params = default_model(nets[i])

    # step B: define body mass
    B0 =  rand(S)

    # step C: set number of timestamps
    t = 300

    # step D: simulate
    out = simulate(params, B0, t)

    # steps D: calculate metrics
    fin_rich = richness(out)
    fin_biomass = total_biomass(out)
    s_div = shannon_diversity(out)

    # 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)

S = 20; # define the number of species
C = 0.2; # define the connectance (complexity) of the network

# construct the food web
Random.seed!(12325) # ensures your network and this one are the same
foodweb_niche = Foodweb(:niche; S = S, C = C)

# construct the equations and fixed parameters
params_niche = default_model(foodweb_niche)

# define bodymasses between 0 and 1 and get S = 20 of them.
Random.seed!(123)
B0 = rand(S)

# simulate using params and bodymasses
# specify number of time steps
t = 300
sim_niche = simulate(params_niche, B0, t)
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.

Warning

Section is no longer a built-in functionality in END. Alain should be able to address

# collect and organise extinctions
extinctions = get_extinct_species(sim_niche)

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
ee1 = DataFrame(who = collect(keys(extinctions)), when = collect(values(extinctions)))

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
exts = ee1[:,2] .+rand.()

# 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.