Code
tolerance <- 0.01This manual is still under development and may be subject to change.
This warning will be removed once the manual is finalized.
This document provides unit tests for the LogoClim NetLogo model. The tests perform near-equality comparisons to validate tolerance expectations during the processing of WorldClim data in NetLogo.
LogoClim integrates WorldClim data into NetLogo models, requiring the conversion of raster data between formats.
WorldClim provides raster data in GeoTIFF format, a high-precision standard for geospatial data with extensive metadata capabilities. However, NetLogo’s GIS extension requires Esri ASCII format, a simpler text-based format with lower precision and limited metadata.
This conversion process inevitably introduces information loss or alteration. These unit tests ensure that discrepancies remain within acceptable tolerance levels, maintaining the reliability of downstream simulations and analyses.
Data used in this report come from the following sources:
The data munging followed the data science workflow outlined by Wickham et al. (2023), as illustrated in Figure B.1. All processes were made using the Quarto publishing system (Allaire et al., n.d.), the NetLogo environment, the R programming language (R Core Team, n.d.), and several R packages.
For data manipulation and workflow, priority was given to packages from the tidyverse, rOpenSci and rspatial ecosystems, as well as other packages adhering to the tidy tools manifesto (Wickham, 2023).
Source: Reproduced from Wickham et al. (2023).
Data extraction was performed using the worldclim_download() function from the orbis R package (Vartanian, 2026c). This function scrapes climate data from the WorldClim website and downloads the relevant GeoTIFF files for the specified variables and time periods.
Following the extraction, the transformation from GeoTIFF to Esri ASCII format is carried out using the worldclim_to_ascii() function from the orbis R package.
Integration with NetLogo (Wilensky, 1999) is facilitated by the logolink R package (Vartanian, 2026b). This package enables the execution of BehaviorSpace experiments directly from R.
Output is extracted in Table and Lists format, containing values, latitude, and longitude for patches, along with global variables that describe the model’s configuration and settings.
No Java dependencies are required. NetLogo bundles its own Java Runtime Environment (JRE), ensuring independent operation regardless of the system’s Java installation.
These tests use the latest release of NetLogo and are automated using GitHub Actions provided by the LogoActions project (Vartanian, 2026a). Each commit to the code repository triggers test execution, ensuring that changes to the codebase are validated against defined tolerance levels.
The data validation is performed using error tolerance tests with expectations functions from the testthat R package (Wickham, 2011). These tests compare the values of the WorldClim data loaded in LogoClim against the original WorldClim dataset.
Each test selects a random variable for a random month or year using the worldclim_random() function from the orbis R package. No seed is set for the random number generator, so results vary between runs.
Elevation, bioclimatic variables, and the models FIO-ESM-2-0, GFDL-ESM4, and HadGEM3-GC31-LL are excluded due to their data limitations.
Two main aspects are considered while performing near equality tests:
To ensure valid statistical analysis, a minimum number of cells is required. Resolution for each country was determined based on its area, aiming to achieve approximately 1,000 cells. This calculation considers the available resolutions and their approximate cell areas at the Equator:
Micronations, like Dominica, were excluded from the analysis due to their small size and limited data availability.
The all.equal and testthat expect_equal functions were used to perform near-equality tests, both relying on relative tolerance. Comparisons are conducted between the original GeoTIFF file and patch values extracted directly from the LogoClim model.
Relative tolerance is proportional to the value of the quantity being measured or calculated. The principle is that larger values can tolerate larger errors.
Given \(x\) and \(y\), relative tolerance can be expressed as:
\[ |x - y| \leq \text{tolerance} \times \max(|x|, |y|) \]
or
\[ \text{tolerance} \geq \frac{|x - y|}{\max(|x|, |y|)} \]
where:
For this analysis, the following tolerance level is used:
tolerance <- 0.01\[ \frac{|x - y|}{\max(|x|, |y|)} \leq 0.01 \]
The Tidyverse Tidy Tools Manifesto (Wickham, 2023), code style guide (Wickham, n.d.-a) and design principles (Wickham, n.d.-b) were followed to ensure consistency and enhance readability.
The pipeline is fully reproducible and can be run again at any time. To ensure consistent results, the renv package (Ushey & Wickham, 2025) was used to manage and restore the R environment. See the README file in the code repository to learn how to run it.
library(brandr)
library(checkmate)
library(cli)
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
library(fs)
library(geodata)
#> Loading required package: terra
#> terra 1.8.86
#>
#> Attaching package: 'terra'
#> The following object is masked from 'package:knitr':
#>
#> spin
#> The following objects are masked from 'package:magrittr':
#>
#> extract, inset
library(ggplot2)
library(here)
library(knitr)
library(leaflet)
library(logolink)
library(magrittr)
library(moments)
library(orbis) # github.com/danielvartan/orbis
library(patchwork)
#>
#> Attaching package: 'patchwork'
#> The following object is masked from 'package:terra':
#>
#> area
library(purrr)
#>
#> Attaching package: 'purrr'
#> The following object is masked from 'package:magrittr':
#>
#> set_names
library(sf)
#> Linking to GEOS 3.14.1, GDAL 3.12.0, PROJ 9.7.0; sf_use_s2() is TRUE
library(stringr)
library(terra)
library(testthat)
#>
#> Attaching package: 'testthat'
#> The following objects are masked from 'package:terra':
#>
#> compare, describe
#> The following objects are masked from 'package:magrittr':
#>
#> equals, is_less_than, not
library(tidyr)
#>
#> Attaching package: 'tidyr'
#> The following object is masked from 'package:terra':
#>
#> extract
#> The following object is masked from 'package:magrittr':
#>
#> extract
library(tidyterra)
#>
#> Attaching package: 'tidyterra'
#> The following object is masked from 'package:stats':
#>
#> filterThe source code for the functions below can be found in the R directory of the code repository.
The here R package (Müller, 2025) is used to construct file paths relative to the project root directory, ensuring portability across different systems.
data_dir <- here("data")if (!dir_exists(data_dir)) {
dir_create(data_dir, recurse = TRUE)
}Setting the JAVA_TOOL_OPTIONS is optional, but recommended to avoid unnecessary messages from the Java Media Framework.
Sys.setenv(JAVA_TOOL_OPTIONS = "-Dcom.sun.media.jai.disableMediaLib=true")model_path <- here("nlogox", "logoclim.nlogox")The list of countries is based on the ISO 3166-1 alpha-3 standard and draw using the ISOcodes R package (Hornik & Buchta, 2025).
country <- country_names("alpha 3") |> sample(1)country
#> Mexico
#> "MEX"The rspatial geodata R package (Hijmans et al., 2024) was used to download country shapes from the GADM database (Hijmans, n.d.).
This while loop ensures that micronations are not selected. Micronation territories are very small and do not achieve the minimum threshold of 1,000 cells.
shape_area
#> [1] 1951230.548country
#> Mexico
#> "MEX"The rotate() function from the terra package (Hijmans, 2026) is used to adjust shapes that cross the International Date Line (e.g., Russian territory).
This adjustment is applied solely for visualizing countries on leaflet. The Esri ASCII transformation function already accounts for such cases.
idl_countries <- c(
"FJI",
"KIR",
"NZL",
"RUS",
"USA"
)leaflet() |>
addTiles() |>
fitBounds(
lng1 = country_shape_leaflet |>
st_bbox() |>
magrittr::extract("xmin") |>
unname(),
lat1 = country_shape_leaflet |>
st_bbox() |>
magrittr::extract("ymin") |>
unname(),
lng2 = country_shape_leaflet |>
st_bbox() |>
magrittr::extract("xmax") |>
unname(),
lat2 = country_shape_leaflet |>
st_bbox() |>
magrittr::extract("ymax") |>
unname()
) |>
addPolygons(
data = country_shape,
fillColor = "transparent",
color = "blue",
weight = 2,
opacity = 1
)