# 09: Troubleshooting / caveats

#### Fallert, S. and Cabral, J.S.

While creating your own simulation, you may encounter issues and errors to which the solution may not be immediately obvious and the resulting error messages can be cryptic and hard to understand. Here we will cover a basic strategy on how to solve them with the example of a simple typo in one of the species traits.

# Debugging

The following code will result in an error:

    library(metaRange)
    library(terra)
    set_verbosity(0)
    raster_file <- system.file("ex/elev.tif", package = "terra")
    r <- rast(raster_file)
    r <- scale(r, center = FALSE, scale = TRUE)
    r <- rep(r, 10)
    landscape <- sds(r)
    names(landscape) <- c("habitat_quality")

    sim <- create_simulation(
        source_environment = landscape,
        ID = "example_simulation",
        seed = 1
    )

    sim$add_species(name = "species_1")
    sim$add_traits(
        species = "species_1",
        population_level = TRUE,
        abundance = 100,
        reproduction_rtae = 0.5,
        carrying_capacity = 1000
    )
    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
            )
        },
        execution_priority = 1
    )
    sim$begin()
    #> Error in eval(expr, envir, enclos): Not compatible with requested type: [type=NULL; target=double].

And it is not immediately obvious what the problem is. The first step to narrow down the problem is to enable extensive verbosity. So, if we run the code again, but this time with `set_verbosity(2)`, we get the following output:

    set_verbosity(2)

    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

    sim$add_species(name = "species_1")
    #> adding species
    #> name: species_1
    sim$add_traits(
        species = "species_1",
        population_level = TRUE,
        abundance = 100,
        reproduction_rtae = 0.5,
        carrying_capacity = 1000
    )
    #> adding traits:
    #> [1] "abundance"         "reproduction_rtae" "carrying_capacity"
    #>
    #> to species:
    #> [1] "species_1"
    #>
    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
            )
        },
        execution_priority = 1
    )
    #> adding process: reproduction
    #> to species:
    #> [1] "species_1"
    #>
    sim$begin()
    #> Starting simualtion.
    #> passed initial sanity checks.
    #> start of time step: 1
    #> |- species_1 : reproduction
    #> Error in eval(expr, envir, enclos): Not compatible with requested type: [type=NULL; target=double].

We can see that the error occurs in the first time step, in the `reproduction` process of “species_1”. With this information, we can now insert a `browser()` function to step into the code to inspect the process and find the source of the error.

    set_verbosity(2)

    sim <- create_simulation(
        source_environment = landscape,
        ID = "example_simulation",
        seed = 1
    )

    sim$add_species(name = "species_1")
    sim$add_traits(
        species = "species_1",
        population_level = TRUE,
        abundance = 100,
        reproduction_rtae = 0.5,
        carrying_capacity = 1000
    )
    sim$add_process(
        species = "species_1",
        process_name = "reproduction",
        process_fun = function() {
            browser()

            ricker_reproduction_model(
                self$traits$abundance,
                self$traits$reproduction_rate,
                self$traits$carrying_capacity * self$sim$environment$current$habitat_quality
            )
        },
        execution_priority = 1
    )
    sim$begin()

As we are in the browser, we are conceptually inside the `reproduction` process of “species_1”. This means we can make use of the `self` keyword to inspect the state of the species.

As a first step, we might want to call `ls()` to see the objects we can inspect.

    # type this in the console,
    # once the browser has halted the code execution
    ls()

    #> [1] "initialize" "name"       "print"      "processes"  "sim"
    #> [6] "traits"

Since the error was about an wrong type being passed to the reproduction function, we can inspect the `traits` of the species to see if they are of the types that we would expect them to be. This means we can just type `self$traits` in the console to see them and we may notice that the `reproduction_rate` is misspelled as `reproduction_rtae`.

    # type this in the console,
    # once the browser has halted the code execution
    self$traits

    #> abundance :  num [1:90, 1:95] 100 100 100 100 100 100 100 100 100 100 ...
    #> carrying_capacity :  num [1:90, 1:95] 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 ...
    #> reproduction_rtae :  num [1:90, 1:95] 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 ...

We can now quit the browser by typing `Q` and then `Enter` in the console and then proceed to fix the typo. Also, we can remove the `browser()` call from the code, as it is not needed anymore.

# General caveats

While metaRange can be used to simulate a wide range of scenarios, there are some caveats to keep in mind.

1. Different scales of the environment and the species

   Since the size and resolution of the environment also describes the spatial size of each population (i.e. one grid cell = one population), it is important to choose scales that are appropriate for the species. This is especially important to keep in mind when simulating multiple species, since they may have different spatial requirements.

2. Evolution and gene flow

   While it is planned for future versions, metaRange doesn’t (currently) support evolution or gene flow.

3. Spatial distortion

   Since metaRange uses raster data to represent the environment, it is important to keep in mind that the raster is a 2D representation of a 3D world. The larger the geographic extent of the environment, the more distorted the raster will be (also depending on the map projection and the resolution).