02: Multiple species

Fallert, S. and Cabral, J.S.

We are going to expand the example from the previous vignette to include multiple species.

Setting up the simulation

As previously, we start by loading the packages and creating the landscape.

Code
library(metaRange)
library(terra)

# find the file
raster_file <- system.file("ex/elev.tif", package = "terra")

# load it
r <- rast(raster_file)

# scale it
r <- scale(r, center = FALSE, scale = TRUE)

r <- rep(r, 10)
landscape <- sds(r)
names(landscape) <- c("habitat_quality")

# plot the first layer of the landscape
plot(landscape[["habitat_quality"]][[1]], main = "Habitat quality")
Figure 1: The habitat quality of the example landscape. Note: higher value = better habitat quality
Figure 1: The habitat quality of the example landscape. Note: higher value = better habitat quality

As before, we create a simulation and add the landscape to it.

Code
sim <- create_simulation(
    source_environment = landscape,
    ID = "example_simulation",
    seed = 1
)
#> number of time steps: 10
#> time step layer mapping: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
#> added environment
#> class       : SpatRasterDataset 
#> subdatasets : 1 
#> dimensions  : 90, 95 (nrow, ncol)
#> nlyr        : 10 
#> resolution  : 0.008333333, 0.008333333  (x, y)
#> extent      : 5.741667, 6.533333, 49.44167, 50.19167  (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#> source(s)   : memory 
#> names       : habitat_quality
#> 
#> created simulation: example_simulation

Adding more species to the simulation

Instead of only adding one species to the simulation, we can just repeat the `add_species() call to add more.

Code
species_to_add <- c("species_1", "species_2")
for (species in species_to_add) {
    sim$add_species(name = species)
}
#> adding species
#> Name: species_1
#> adding species
#> Name: species_2

If you are at any point wondering which, or how many species are in the simulation, you can use the species_names() method.

Code
sim$species_names()
#> [1] "species_2" "species_1"

Adding traits to (multiple) species

The add_traits() method is able to add (multiple) traits to multiple species at once, which is useful when setting up a large number of species with the same traits. So instead of only specifying one species argument, we can specify a vector of species names, all of which will get the same traits.

Code
sim$add_traits(
    species = c("species_1", "species_2"),
    population_level = TRUE,
    abundance = 100
)
#> adding traits:
#> [1] "abundance"
#> 
#> to species:
#> [1] "species_1" "species_2"
#> 

If we would want to add a trait to all species in the simulation, without having to type their names, we could use the already mentioned species_names() method to get a vector of all species names and then use that as the species argument.

Code
sim$add_traits(
    species = sim$species_names(),
    population_level = TRUE,
    reproduction_rate = 0.5,
    carrying_capacity = 1000
)
#> adding traits:
#> [1] "reproduction_rate" "carrying_capacity"
#> 
#> to species:
#> [1] "species_2" "species_1"
#> 

Since we only have the two species in the simulation this would be equivalent to the previous call.

Adding processes

Until now, we have two species in the simulation that are virtually identical. In order to make them behave differently, we can add different processes to them.

Reproduction

We are going to use the same reproduction process as in the previous vignette, but we will vary the influence of the habitat quality. In the case of species 1, the habitat quality will only affect the carrying capacity of the habitat.

Code
sim$add_process(
    species = "species_1",
    process_name = "reproduction",
    process_fun = function() {
        ricker_reproduction_model(
            self$traits$abundance,
            self$traits$reproduction_rate,
            self$traits$carrying_capacity * self$sim$environment$current$habitat_quality
        )
        print(
            paste0(self$name, " mean abundance: ", mean(self$traits$abundance))
        )
    },
    execution_priority = 1
)
#> adding process: reproduction
#> to species:
#> [1] "species_1"
#> 

In the case of species 2, the habitat quality will only affect the reproduction rate.

Code
sim$add_process(
    species = "species_2",
    process_name = "reproduction",
    process_fun = function() {
        self$traits$abundance <-
            ricker_reproduction_model(
                self$traits$abundance,
                self$traits$reproduction_rate * self$sim$environment$current$habitat_quality,
                self$traits$carrying_capacity
            )
        print(
            paste0(self$name, " mean abundance: ", mean(self$traits$abundance))
        )
    },
    execution_priority = 1
)
#> adding process: reproduction
#> to species:
#> [1] "species_2"
#> 

Executing the simulation

Now we can execute the simulation again and compare the results.

Code
set_verbosity(0)
sim$begin()
#> [1] "species_1 mean abundance: 84.1732579542268"
#> [1] "species_2 mean abundance: 83.9862282167713"
#> [1] "species_1 mean abundance: 127.598064388471"
#> [1] "species_2 mean abundance: 128.093897941553"
#> [1] "species_1 mean abundance: 185.433176212344"
#> [1] "species_2 mean abundance: 187.269476742542"
#> [1] "species_1 mean abundance: 254.974925085775"
#> [1] "species_2 mean abundance: 256.540644607799"
#> [1] "species_1 mean abundance: 328.335965177599"
#> [1] "species_2 mean abundance: 325.349187830559"
#> [1] "species_1 mean abundance: 394.79908318955"
#> [1] "species_2 mean abundance: 384.503328576066"
#> [1] "species_1 mean abundance: 446.224976588256"
#> [1] "species_2 mean abundance: 430.718982598954"
#> [1] "species_1 mean abundance: 480.705159122178"
#> [1] "species_2 mean abundance: 464.734433159244"
#> [1] "species_1 mean abundance: 501.356439544315"
#> [1] "species_2 mean abundance: 488.741052995808"
#> [1] "species_1 mean abundance: 512.803082103058"
#> [1] "species_2 mean abundance: 505.185406158201"
Code
# define a nice color palette
plot_cols <- hcl.colors(100, "BluYl", rev = TRUE)
plot(
    sim,
    obj = "species_1",
    name = "abundance",
    main = "Species 1: abundance",
    col = plot_cols
)
Figure 2: The resulting abundance distribution of species 1 after 10 simulation time steps.
Figure 2: The resulting abundance distribution of species 1 after 10 simulation time steps.
Code
plot(
    sim,
    obj = "species_2",
    name = "abundance",
    main = "Species 2: abundance",
    col = plot_cols
)
Figure 3: The resulting abundance distribution of species 2 after 10 simulation time steps.
Figure 3: The resulting abundance distribution of species 2 after 10 simulation time steps.