This vignette analyses European anchovy (Engraulis
encrasicolus) in the Mediterranean Sea using Bio-ORACLE v3 surface
layers, OBIS occurrences, and a continuous presence-background SDM.
climniche treats above-threshold suitability values as
reference weights.
library(climniche)
case_path <- system.file("extdata/mediterranean_anchovy", package = "climniche")
# Prepared tables stored with the package.
metric_summary <- read.csv(
file.path(case_path, "anchovy_climniche_metric_summary.csv")
)
variable_contributions <- read.csv(
file.path(case_path, "anchovy_climniche_variable_contributions.csv")
)
layer_manifest <- read.csv(
file.path(case_path, "anchovy_biooracle_layer_manifest.csv")
)
sdm_settings <- read.csv(
file.path(case_path, "anchovy_presence_background_sdm_settings.csv")
)
fit_settings <- read.csv(
file.path(case_path, "anchovy_climniche_fit_settings.csv")
)
predictor_screen <- read.csv(
file.path(case_path, "anchovy_predictor_correlation_vif_screen.csv")
)Prepared inputs
The environmental data are Bio-ORACLE v3 surface layers. Baseline time layers were averaged for current conditions; future rasters use the same variables under SSP2-4.5 at the 2050 time coordinate.
# Use readable scenario labels in the printed table.
layer_table <- layer_manifest
layer_table[["future_scenario"]] <- "SSP2-4.5"
unique(layer_table[, c(
"depth", "current_time", "future_scenario", "future_time"
)])
#> depth current_time
#> 1 surface (depthsurf) Bio-ORACLE v3 baseline time layers averaged
#> future_scenario future_time
#> 1 SSP2-4.5 2050-01-01T00:00:00Z
subset(layer_table, retained_for_climniche, c(
"label", "depth", "current_time", "future_scenario", "future_time"
))
#> label depth
#> 1 Mean temperature surface (depthsurf)
#> 2 Temperature range surface (depthsurf)
#> 4 Salinity range surface (depthsurf)
#> 6 Mean pH surface (depthsurf)
#> 7 Mean chlorophyll surface (depthsurf)
#> 8 Mean current speed surface (depthsurf)
#> 9 Current speed range surface (depthsurf)
#> current_time future_scenario
#> 1 Bio-ORACLE v3 baseline time layers averaged SSP2-4.5
#> 2 Bio-ORACLE v3 baseline time layers averaged SSP2-4.5
#> 4 Bio-ORACLE v3 baseline time layers averaged SSP2-4.5
#> 6 Bio-ORACLE v3 baseline time layers averaged SSP2-4.5
#> 7 Bio-ORACLE v3 baseline time layers averaged SSP2-4.5
#> 8 Bio-ORACLE v3 baseline time layers averaged SSP2-4.5
#> 9 Bio-ORACLE v3 baseline time layers averaged SSP2-4.5
#> future_time
#> 1 2050-01-01T00:00:00Z
#> 2 2050-01-01T00:00:00Z
#> 4 2050-01-01T00:00:00Z
#> 6 2050-01-01T00:00:00Z
#> 7 2050-01-01T00:00:00Z
#> 8 2050-01-01T00:00:00Z
#> 9 2050-01-01T00:00:00ZThe current reference layer is a continuous suitability raster from a presence-background SDM. Background cells are sampled Mediterranean cells outside occurrence cells; they are not confirmed absences. The maximum TSS threshold removes low suitability cells from the reference set. Suitability values above the threshold remain continuous weights.
subset(
sdm_settings,
setting == "presence_cell_count" |
setting == "background_cell_count" |
setting == "background_to_presence_ratio" |
setting == "sdm_test_auc" |
setting == "sdm_test_tss" |
setting == "sdm_threshold"
)
#> setting value
#> 5 presence_cell_count 462
#> 7 background_cell_count 462
#> 8 background_to_presence_ratio 1.00
#> 17 sdm_threshold 0.6165
#> 18 sdm_test_auc 0.859
#> 19 sdm_test_tss 0.572Predictor screening was completed before the climniche
fit. The retained variables are:
climniche_predictors <- subset(
predictor_screen,
role == "climniche exposure calculation" & retained
)
subset(climniche_predictors, retained, c("label", "vif_after_screening"))
#> label vif_after_screening
#> 10 Mean temperature 1.440695
#> 11 Temperature range 1.514125
#> 13 Salinity range 1.445024
#> 15 Mean pH 2.102541
#> 16 Mean chlorophyll 1.587461
#> 17 Mean current speed 1.793713
#> 18 Current speed range 1.744511Reproducing the climniche step
This example uses fit_climniche_terra() because the
prepared Bio-ORACLE layers are terra rasters. The current and future
layers must be aligned, and the suitability map is passed to
occupied as a continuous reference layer.
occupied_threshold removes low suitability cells without
converting the remaining values to one.
# Use the maximum TSS threshold to remove low suitability cells.
threshold_row <- subset(sdm_settings, setting == "sdm_threshold")
sdm_threshold <- as.numeric(threshold_row[["value"]])
# Keep the Bio-ORACLE variables retained after predictor screening.
climniche_predictors <- subset(
predictor_screen,
role == "climniche exposure calculation" & retained
)
selected_predictors <- climniche_predictors[["variable"]]
predictor_labels <- setNames(
climniche_predictors[["label"]],
selected_predictors
)
# The suitability raster supplies continuous reference weights.
fit <- fit_climniche_terra(
current = current_layers[[selected_predictors]],
future = future_layers[[selected_predictors]],
occupied = anchovy_suitability,
occupied_threshold = sdm_threshold,
domain = mediterranean_sea_mask,
sensitivity = predictor_sensitivity
)
climniche_summary(fit)Niche-relative decomposition
The fit returns four quantities. Climatic Displacement is the distance from current to future conditions in the fitted sensitivity weighted climatic space. Niche Distance Shift is the signed change in distance from the current realised niche centre. Climatic Reconfiguration is the remaining non-radial component, calculated from the identity \(D_i^2 = R_i^2 + C_i^2\). Niche Boundary Exceedance is the positive excess beyond the chosen weighted quantile of current reference-cell distances from the realised niche centre.
subset(
fit_settings,
setting == "boundary_quantile" |
setting == "tolerance" |
setting == "boundary_exceedance_tolerance"
)
#> setting value
#> 19 boundary_quantile 0.95
#> 20 tolerance 0.886937582984278
#> 22 boundary_exceedance_tolerance 0
metric_summary[, c(
"n", "reference_weight_sum", "boundary_quantile",
"mean_climate_change_amount", "mean_niche_distance_change",
"prop_outside_niche", "mean_niche_boundary_exceedance"
)]
#> n reference_weight_sum boundary_quantile mean_climate_change_amount
#> 1 10374 7265.403 0.95 4.282655
#> mean_niche_distance_change prop_outside_niche mean_niche_boundary_exceedance
#> 1 2.725927 0.0880985 0.1676494Variable contributions summarize fitted change; they should not be interpreted causally.
variable_contributions
#> variable mean_contribution abs_mean_contribution
#> 1 ph_mean 14.7283258 14.7283258
#> 2 temperature_range 2.2908469 2.2908469
#> 3 salinity_range 1.1141710 1.1141710
#> 4 temperature_mean 0.5162404 0.5162404
#> 5 sea_water_speed_range 0.4613986 0.4613986
#> interpretation
#> 1 positive fitted variable contribution
#> 2 positive fitted variable contribution
#> 3 positive fitted variable contribution
#> 4 positive fitted variable contribution
#> 5 positive fitted variable contributionMediterranean maps
The map figure shows the four continuous reported quantities within current suitable habitat.
metric_maps <- plot_climniche_maps(
fit,
occupied = anchovy_suitability,
occupied_only = TRUE,
occupied_threshold = sdm_threshold,
study_region = mediterranean_boundary,
degree_labels = "hemisphere",
legend_title = NULL,
legend_position = "bottom"
)
metric_maps
Summary figure
The summary figure uses one weighted plane for Climatic Displacement and Niche Distance Shift and a second for Climatic Reconfiguration and Niche Boundary Exceedance. It also shows model-derived variable contribution shares and weighted distributions of the four reported quantities.
summary_figure <- plot_climniche_summary_figure(
fit,
scope = "current",
top_variables = 6,
variable_labels = predictor_labels,
title = NULL
)
summary_figure