How environmental conditions influence the distribution of species is a central study question in ecology. In this tutorial we will show how to implement a simple niche suitability model in metaRange. For this, we will create a landscape with two environmental variables (temperature and precipitation) and then add two species to it, that have different environmental preferences. We are going to give the two species the same traits otherwise and then run the simulation for 10 time steps to see the impact of the different environmental preferences.
First we load the packages and create the example landscape.
Now we can (again) turn the raster into an SDS
with one
layer per time step.
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 : 2
#> dimensions : 90, 95 (nrow, ncol)
#> nlyr : 10, 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 : temperature, precipitation
#>
#> created simulation: example_simulation
sim$add_species(name = "species_1")
#> adding species
#> Name: species_1
sim$add_species(name = "species_2")
#> adding species
#> Name: species_2
To start, we add the same traits as in the previous tutorials and
also add a trait called climate_suitability
, where we will
store the information about how suitable the environment in each cell is
for the population that lives there.
sim$add_traits(
species = c("species_1", "species_2"),
population_level = TRUE,
abundance = 500,
climate_suitability = 1,
reproduction_rate = 0.3,
carrying_capacity = 1000
)
#> adding traits:
#> [1] "abundance" "climate_suitability" "reproduction_rate"
#> [4] "carrying_capacity"
#>
#> to species:
#> [1] "species_1" "species_2"
#>
Contrary to the above, some traits may not require to be stored at
the population level. In this example, this could be the case for the
environmental preferences of a species. If we assume that they are a
property of the species as a whole (i.e. the same for all populations),
we can set the parameter population_level
to
FALSE
and the traits will be added as they are, without
further processing.
In order to make the simulation more interesting, we can give both species different environmental preferences for the two environmental variables in the simulation environment (temperature & precipitation).
Note that the names of the traits are arbitrary and can be chosen by the user and that there is no predetermined connection between e.g. “min_temperature” and the temperature variable in the environment. To establish these connections, the user needs to add species processes that access the correct traits and use them in a sensible way. This is why meaningful trait names are important.
sim$add_traits(
species = "species_1",
population_level = FALSE,
max_temperature = 300, # Kelvin
optimal_temperature = 288,
min_temperature = 280,
max_precipitation = 1000, # mm
optimal_precipitation = 700,
min_precipitation = 200
)
#> adding traits:
#> [1] "max_temperature" "optimal_temperature" "min_temperature"
#> [4] "max_precipitation" "optimal_precipitation" "min_precipitation"
#>
#> to species:
#> [1] "species_1"
#>
sim$add_traits(
species = "species_2",
population_level = FALSE,
max_temperature = 290,
optimal_temperature = 285,
min_temperature = 270,
max_precipitation = 1000,
optimal_precipitation = 500,
min_precipitation = 0
)
#> adding traits:
#> [1] "max_temperature" "optimal_temperature" "min_temperature"
#> [4] "max_precipitation" "optimal_precipitation" "min_precipitation"
#> to species:
#> [1] "species_2"
#>
To calculate the suitability, we use the metaRange function
calculate_suitability()
that was adapted from a formula
published by Yin et al. in 1995 (Ref. 1) and simplified by Yan and Hunt
in 1999 (eq:4 in Ref. 2). The formula takes the three cardinal values of
an environmental niche (minimum tolerable value, optimal vale and
maximum tolerable value) and constructs a suitability curve based on a
beta distribution.
In the following code we add a process to both species that calculates the environmental suitability for precipitation and temperature and then multiplies the values to create a joint suitability over the two niches. Note that one could also define a custom function to calculate the suitability, if this built-in function does not adequately describe the ecology of the target species.
sim$add_process(
species = c("species_1", "species_2"),
process_name = "calculate_suitability",
process_fun = function() {
self$traits$climate_suitability <-
calculate_suitability(
self$traits$max_temperature,
self$traits$optimal_temperature,
self$traits$min_temperature,
self$sim$environment$current$temperature
) *
calculate_suitability(
self$traits$max_precipitation,
self$traits$optimal_precipitation,
self$traits$min_precipitation,
self$sim$environment$current$precipitation
)
},
execution_priority = 1
)
#> adding process: calculate_suitability
#> to species:
#> [1] "species_1" "species_2"
#>
As in the previous tutorials, we use a Ricker reproduction model to calculate the new abundance of the species, but this time we let both the carrying capacity and the reproduction rate depend on the niche suitability of the environment.
sim$add_process(
species = c("species_1", "species_2"),
process_name = "reproduction",
process_fun = function() {
self$traits$abundance <-
ricker_reproduction_model(
self$traits$abundance,
self$traits$reproduction_rate * self$traits$climate_suitability,
self$traits$carrying_capacity * self$traits$climate_suitability
)
},
execution_priority = 2
)
#> adding process: reproduction
#> to species:
#> [1] "species_1" "species_2"
#>
Now, we can execute the simulation and compare the results.
set_verbosity(1)
sim$begin()
#> Starting simualtion.
#> start of time step: 1
#> end of time step: 1
#> 0.098 secs remaining (estimate)
#> 10 % done
#> start of time step: 2
#> end of time step: 2
#> 0.12 secs remaining (estimate)
#> 20 % done
#> start of time step: 3
#> end of time step: 3
#> 0.077 secs remaining (estimate)
#> 30 % done
#> start of time step: 4
#> end of time step: 4
#> 0.092 secs remaining (estimate)
#> 40 % done
#> start of time step: 5
#> end of time step: 5
#> 0.051 secs remaining (estimate)
#> 50 % done
#> start of time step: 6
#> end of time step: 6
#> 0.041 secs remaining (estimate)
#> 60 % done
#> start of time step: 7
#> end of time step: 7
#> 0.031 secs remaining (estimate)
#> 70 % done
#> start of time step: 8
#> end of time step: 8
#> 0.021 secs remaining (estimate)
#> 80 % done
#> start of time step: 9
#> end of time step: 9
#> 0.01 secs remaining (estimate)
#> 90 % done
#> start of time step: 10
#> end of time step: 10
#> 0 secs remaining (estimate)
#> 100 % done
#> Simulation: 'example_simulation' finished
#> Exiting the Simulation
#> Runtime: 0.12 secs
Yin, X., Kropff, M.J., McLaren, G., Visperas, R.M., (1995) A nonlinear model for crop development as a function of temperature, Agricultural and Forest Meteorology, Volume 77, Issues 1-2, Pages 1–16, doi:10.1016/0168-1923(95)02236-Q
Yan, W., Hunt, L.A. (1999) An Equation for Modelling the Temperature Response of Plants using only the Cardinal Temperatures, Annals of Botany, Volume 84, Issue 5, Pages 607–614, ISSN 0305-7364, doi:10.1006/anbo.1999.0955