Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .buildlibrary
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ValidationKey: '54982535'
ValidationKey: '55416690'
AutocreateReadme: yes
AcceptedWarnings:
- 'Warning: package .* was built under R version'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
options(repos = c(pikpiam = 'https://pik-piam.r-universe.dev',
CRAN = Sys.getenv('RSPM')))
pak::pak()

- name: Run pre-commit checks
shell: bash
run: |
Expand Down
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ cff-version: 1.2.0
message: If you use this software, please cite it using the metadata from this file.
type: software
title: 'mrvalidation: madrat data preparation for validation purposes'
version: 2.67.1
date-released: '2026-05-12'
version: 2.69.0
date-released: '2026-05-28'
abstract: Package contains routines to prepare data for validation exercises.
authors:
- family-names: Bodirsky
Expand Down
5 changes: 3 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Type: Package
Package: mrvalidation
Title: madrat data preparation for validation purposes
Version: 2.67.1
Date: 2026-05-12
Version: 2.69.0
Date: 2026-05-28
Authors@R: c(
person("Benjamin Leon", "Bodirsky", , "bodirsky@pik-potsdam.de", role = c("aut", "cre")),
person("Stephen", "Wirth", role = "aut"),
Expand Down Expand Up @@ -53,6 +53,7 @@ Imports:
reshape2,
rlang,
stringr,
terra,
tidyr,
utils,
withr,
Expand Down
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ importFrom(rlang,.data)
importFrom(stringr,str_extract)
importFrom(stringr,str_match)
importFrom(stringr,str_split)
importFrom(terra,aggregate)
importFrom(terra,extract)
importFrom(terra,project)
importFrom(terra,rast)
importFrom(tidyr,drop_na)
importFrom(tidyr,expand_grid)
importFrom(tidyr,nest)
Expand Down
83 changes: 71 additions & 12 deletions R/calcValidBII.R
Original file line number Diff line number Diff line change
@@ -1,28 +1,87 @@
#' @title calcValidBII
#' @description validation for the Biodiversity Intactness Index (BII)
#' @author Michael Crawford
#' @description Validation for the Biodiversity Intactness Index (BII), side-by-side
#' from two NHM sources:
#' * Phillips et al. 2021 (BII-BTE, DOI 10.5519/he1eqmg1), country-level
#' 1970-2014.
#' * De Palma et al. 2024 NHM v2.1.1 (DOI 10.5519/k33reyb6), cellular
#' 5-yearly 2000-2020, aggregated to ISO here.
#' v2 differs from v1 in three steps: stricter primary-vegetation baseline
#' (minimally/lightly-used primary only, vs v1's all-primary including
#' intensely-used sites), logit (not log) transform, and balanced Bray-Curtis
#' (abundance-weighted) compositional similarity in place of v1's asymmetric
#' Jaccard (species-identity only). v2 absolute BII is markedly lower than v1,
#' with a non-uniform gap that depends on land-use intensity, so the two
#' series are NOT splice-compatible and are kept as separate model labels.
#'
#' @return Country-level MAgPIE object
#' MAgPIE's own BII output (modules/44_biodiversity, coefficients from
#' Leclère et al. 2020 "Bending the Curve" via PREDICTS) is on the v1 scale,
#' so it aligns with Phillips et al. 2021 in absolute terms but sits markedly
#' above De Palma et al. 2024 v2 (gap depends on land-use intensity). For
Comment thread
flohump marked this conversation as resolved.
Outdated
#' absolute-level validation use Phillips; for harmonized (change-from-baseline)
#' plots either series works, but mixing MAgPIE projections with v2 historical
#' on a non-harmonized axis is misleading.
#' Note: v2.1.1's land-use driver is also LUH2 (CSIRO-downscaled via Hoskins
#' et al. 2016), so MAgPIE and v2.1.1 share the LU framework -- only the
Comment thread
flohump marked this conversation as resolved.
Outdated
#' PREDICTS coefficient version differs.
#' @author Michael Crawford, Florian Humpenoeder
#' @seealso \code{\link{readBII}}, \code{\link{readBIIv2}}, \code{\link{downloadBIIv2}}
#'
#' @return Country-level MAgPIE object: "Phillips et al" + "De Palma et al 2024"
#' under variable "Biodiversity|BII".
#'
#' @examples
#'
#' \dontrun{
#' calcOutput("ValidBII")
#' }
#'
#' @importFrom madrat toolAggregate toolCountryFill toolNAreplace

calcValidBII <- function() {

bii <- readSource("BII", subtype = "historical", subset = "bii")
bii <- add_dimension(bii, dim = 3.2, add = "model", nm = "Phillips et al")
getNames(bii, dim = "variable") <- "Biodiversity|BII"
# Phillips et al. 2021: already country-level.
biiV1 <- readSource("BII", subtype = "historical", subset = "bii")
biiV1 <- add_dimension(biiV1, dim = 3.2, add = "model", nm = "Phillips et al")
getNames(biiV1, dim = "variable") <- "Biodiversity|BII"

# De Palma et al. 2024 NHM v2.1.1: cellular -> ISO. toolNAreplace masks both
# value and weight to 0 where either is NA, so toolAggregate's weighted mean
# ignores water/missing cells instead of propagating NA (the toolAggregate
# weighted path multiplies x*weight, so raw NAs would zero out whole
# countries). Same pattern as mrcommons::calcLanduseIntensity, calcValidTau.
# nm must not contain "." (magclass parses dots as sub-dim separators), so
# the bare label "De Palma et al 2024" -- v2.1.1 details live in BIIv2 source.
biiV2cell <- readSource("BIIv2")
cellArea <- calcOutput("LandArea", cells = "lpjcell", aggregate = FALSE)
naFix <- toolNAreplace(x = biiV2cell, weight = cellArea)
biiV2 <- toolAggregate(naFix$x, weight = naFix$weight, to = "iso", dim = 1,
zeroWeight = "setNA")
biiV2 <- toolCountryFill(biiV2, fill = NA, verbosity = 2)
biiV2 <- add_dimension(biiV2, dim = 3.1, add = "scenario", nm = "historical")
biiV2 <- add_dimension(biiV2, dim = 3.2, add = "model", nm = "De Palma et al 2024")
getNames(biiV2, dim = "variable") <- "Biodiversity|BII"

# mbind unions one differing dim only; v1 and v2 differ on both years and
# model, so pad years to the union first.
yrsAll <- sort(union(getYears(biiV1), getYears(biiV2)))
missingInV1 <- setdiff(yrsAll, getYears(biiV1))
missingInV2 <- setdiff(yrsAll, getYears(biiV2))
if (length(missingInV1)) biiV1 <- add_columns(biiV1, addnm = missingInV1, dim = 2)
if (length(missingInV2)) biiV2 <- add_columns(biiV2, addnm = missingInV2, dim = 2)
biiV1 <- biiV1[, yrsAll, ]
biiV2 <- biiV2[, yrsAll, ]

land <- calcOutput("FAOLand", aggregate = FALSE)
landArea <- land[, "y2015", "6601|Land area"] # total land is stable through time, so I arbitrarily use y2015
bii <- mbind(biiV1, biiV2)

return(list(x = bii,
weight = landArea,
unit = "unitless",
description = "Historical BII for 1970-2014"))
land <- calcOutput("FAOLand", aggregate = FALSE)
landArea <- land[, "y2015", "6601|Land area"] # land area stable across time

return(list(x = bii,
weight = landArea,
unit = "unitless",
description = paste("Historical BII from two NHM sources:",
"Phillips et al. 2021 (DOI 10.5519/he1eqmg1, 1970-2014)",
"and De Palma et al. 2024 v2.1.1 (DOI 10.5519/k33reyb6, 2000-2020).",
"v1 and v2 use different methodologies and are NOT on the same",
"absolute scale -- compare within a series, not across.")))
}
83 changes: 83 additions & 0 deletions R/downloadBIIv2.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#' @title downloadBIIv2
#' @description Download the Biodiversity Intactness Index v2.1.1 (Open Access,
#' Limited Release) from the Natural History Museum (De Palma et al. 2024,
#' \doi{10.5519/k33reyb6}). Global 5 arc-minute GeoTIFFs for 2000, 2005, 2010,
#' 2015, 2020.
#' @seealso \url{https://data.nhm.ac.uk/dataset/bii-developed-by-nhm-v2-1-1-limited-release},
#' \code{\link{downloadBII}}, \code{\link{readBIIv2}}
#' @author Michael Crawford, Florian Humpenoeder
Comment thread
flohump marked this conversation as resolved.
Outdated
#'
#' @return Metadata on downloaded BII v2.1.1 data.
#'
#' @details
#' The NHM CKAN resource URL returns HTTP 403 to non-browser clients
#' (Cloudflare). The portal's content-addressable
#' \code{/downloads/direct/<sha>.zip} endpoint bypasses the challenge.
#' If the URL becomes unreachable, download the ZIP manually via a browser
#' from the landing page and place it as 'bii-v2-1-1-nhm-data-portal.zip'
#' in this source folder.
#'
#' @examples
#'
#' \dontrun{
#' downloadSource("BIIv2")
#' }
#'
#' @importFrom utils download.file person unzip

downloadBIIv2 <- function() {

# nolint start

url <- "https://data.nhm.ac.uk/downloads/direct/8161226fda7a36ca0b94f2becee9afe1b318d0a8.zip"
zipFile <- "bii-v2-1-1-nhm-data-portal.zip"

if (!file.exists(zipFile)) {
tryCatch(
utils::download.file(url, destfile = zipFile, mode = "wb"),
error = function(e) {
stop("Automated NHM download failed (Cloudflare likely). Manually download from ",
"https://data.nhm.ac.uk/dataset/bii-developed-by-nhm-v2-1-1-limited-release ",
"and place '", zipFile, "' in this source folder. Original error: ", conditionMessage(e))
}
)
}

# Cloudflare challenge stub is ~6 KB; real ZIP is ~45 MB.
if (file.size(zipFile) < 1e7) {
stop("'", zipFile, "' is too small (", file.size(zipFile),
" bytes) -- likely a Cloudflare challenge page. Manually download via browser.")
}

# Outer ZIP holds an inner ZIP (resource-ID-named) + manifest.json; inner ZIP has the 5 GeoTIFFs.
utils::unzip(zipFile, exdir = ".")
innerZip <- "c4c281c4-befa-4e1b-a162-ba2f25e5ae82.zip"
if (!file.exists(innerZip)) {
stop("Inner archive '", innerZip, "' missing -- NHM ZIP layout may have changed.")
}
utils::unzip(innerZip, exdir = ".")

return(list(url = "https://data.nhm.ac.uk/dataset/bii-developed-by-nhm-v2-1-1-limited-release",
doi = "https://doi.org/10.5519/k33reyb6",
title = "The Biodiversity Intactness Index developed by The Natural History Museum, London, v2.1.1 (Open Access, Limited Release)",
unit = "Percentage (0-100)",
author = list(person("Adriana", "De Palma"),
person("Sara", "Contu"),
person("Gareth E", "Thomas"),
person("Connor", "Duffin"),
person("Sabine", "Nix"),
person("Andy", "Purvis")),
version = "v2.1.1",
release_date = "2024-10-09",
description = paste("Global gridded BII at 5 arc-minute resolution for",
"2000, 2005, 2010, 2015, 2020.",
"Values 0-100 (100 = fully intact)."),
license = "CC-BY-NC-SA 4.0",
reference = paste("Adriana De Palma; Sara Contu; Gareth E Thomas; Connor Duffin; Sabine Nix; Andy Purvis (2024).",
"The Biodiversity Intactness Index developed by The Natural History Museum, London,",
"v2.1.1 (Open Access, Limited Release) [Data set]. Natural History Museum.",
"https://doi.org/10.5519/k33reyb6"))
)

# nolint end
}
62 changes: 62 additions & 0 deletions R/readBIIv2.R
Comment thread
flohump marked this conversation as resolved.
Outdated
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#' @title readBIIv2
#' @description Read the De Palma et al. 2024 NHM BII v2.1.1 rasters and return
#' a cellular magclass on the 67420-cell lpjcell grid. Country-aggregation is
#' left to the consumer (calcValidBII).
#' @seealso \code{\link{readBII}}, \code{\link{downloadBIIv2}}, \code{\link{calcValidBII}}
#' @author Michael Crawford, Florian Humpenoeder
Comment thread
flohump marked this conversation as resolved.
Outdated
#'
#' @return magclass: x.y.iso x year x "bii", fraction (0-1). Source is percent
#' (0-100); divided by 100 here to match readBII (Phillips et al. 2021).
#'
#' @details
#' 5 arc-minute -> 30 arc-minute via terra::aggregate(fact = 6, fun = "mean")
#' -- unweighted mean is fine within a 6x6 block (<1% cell-area variation at
#' 80 deg lat, BII is intensive). terra::project pins the result to the
#' canonical 0.5-deg grid. terra::extract samples the 67420 lpjcell
#' coordinates from mstools::toolGetMappingCoord2Country.
#'
#' Data sub-dim is named "variable" (not the cellular-read default "data")
#' so calcValidBII can use \code{getNames(x, dim = "variable") <- ...} on
#' both v1 and v2 inputs.
#'
#' @examples
#'
#' \dontrun{
#' readSource("BIIv2")
#' }
#'
#' @importFrom magclass as.magpie mbind getCells getNames getSets getYears
#' @importFrom terra rast aggregate project extract
#' @importFrom mstools toolGetMappingCoord2Country

readBIIv2 <- function() {

years <- c(2000, 2005, 2010, 2015, 2020)
files <- setNames(sprintf("bii-%d_v2-1-1.tif", years), as.character(years))
missingFiles <- files[!file.exists(files)]
if (length(missingFiles)) {
stop("Missing BII v2.1.1 GeoTIFF(s): ", paste(missingFiles, collapse = ", "),
". Run downloadSource(\"BIIv2\") first.")
}

map <- toolGetMappingCoord2Country(pretty = TRUE)
resolution <- terra::rast(resolution = 0.5)

.read <- function(year, file) {
r <- terra::rast(file)
r <- terra::aggregate(r, fact = 6, fun = "mean", na.rm = TRUE)
r <- terra::project(r, resolution)
vals <- terra::extract(r, map[c("lon", "lat")])[, 2] # col 1 = ID
m <- as.magpie(vals, spatial = 1)
getYears(m) <- year
getNames(m) <- "bii"
m
}

out <- do.call(mbind, Map(.read, years, files))
getCells(out) <- paste(map$coords, map$iso, sep = ".")
getSets(out) <- c("x.y.iso", "t", "variable")
out <- out / 100 # percent -> fraction (parity with readBII)

return(out)
}
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# madrat data preparation for validation purposes

R package **mrvalidation**, version **2.67.1**
R package **mrvalidation**, version **2.69.0**

[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.4317826.svg)](https://doi.org/10.5281/zenodo.4317826) [![R build status](https://github.com/pik-piam/mrvalidation/workflows/check/badge.svg)](https://github.com/pik-piam/mrvalidation/actions) [![codecov](https://codecov.io/gh/pik-piam/mrvalidation/branch/master/graph/badge.svg)](https://app.codecov.io/gh/pik-piam/mrvalidation) [![r-universe](https://pik-piam.r-universe.dev/badges/mrvalidation)](https://pik-piam.r-universe.dev/builds)

Expand All @@ -21,13 +21,13 @@ The additional repository can be made available permanently by adding the line a

After that the most recent version of the package can be installed using `install.packages`:

```r
```r
install.packages("mrvalidation")
```

Package updates can be installed using `update.packages` (make sure that the additional repository has been added before running that command):

```r
```r
update.packages()
```

Expand All @@ -39,7 +39,7 @@ In case of questions / problems please contact Benjamin Leon Bodirsky <bodirsky@

To cite package **mrvalidation** in publications use:

Bodirsky B, Wirth S, Karstens K, Humpenoeder F, Stevanovic M, Mishra A, Biewald A, Weindl I, Beier F, Chen D, Crawford M, Leip D, Molina Bacca E, Kreidenweis U, W. Yalew A, von Jeetze P, Wang X, Dietrich J, Alves M (2026). "mrvalidation: madrat data preparation for validation purposes." doi:10.5281/zenodo.4317826 <https://doi.org/10.5281/zenodo.4317826>, Version: 2.67.1, <https://github.com/pik-piam/mrvalidation>.
Bodirsky B, Wirth S, Karstens K, Humpenoeder F, Stevanovic M, Mishra A, Biewald A, Weindl I, Beier F, Chen D, Crawford M, Leip D, Molina Bacca E, Kreidenweis U, W. Yalew A, von Jeetze P, Wang X, Dietrich J, Alves M (2026). "mrvalidation: madrat data preparation for validation purposes." doi:10.5281/zenodo.4317826 <https://doi.org/10.5281/zenodo.4317826>, Version: 2.69.0, <https://github.com/pik-piam/mrvalidation>.

A BibTeX entry for LaTeX users is

Expand All @@ -48,9 +48,9 @@ A BibTeX entry for LaTeX users is
title = {mrvalidation: madrat data preparation for validation purposes},
author = {Benjamin Leon Bodirsky and Stephen Wirth and Kristine Karstens and Florian Humpenoeder and Mishko Stevanovic and Abhijeet Mishra and Anne Biewald and Isabelle Weindl and Felicitas Beier and David Chen and Michael Crawford and Debbora Leip and Edna {Molina Bacca} and Ulrich Kreidenweis and Amsalu {W. Yalew} and Patrick {von Jeetze} and Xiaoxi Wang and Jan Philipp Dietrich and Marcos Alves},
doi = {10.5281/zenodo.4317826},
date = {2026-05-12},
date = {2026-05-28},
year = {2026},
url = {https://github.com/pik-piam/mrvalidation},
note = {Version: 2.67.1},
note = {Version: 2.69.0},
}
```
33 changes: 30 additions & 3 deletions man/calcValidBII.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading