Shift and rotate
In this tutorial, we will apply the Shift and Rotate technique to generate realistic maps of predictors to provide a null sample for the performance of an SDM. We will also look at the quantile mapping function, which ensures that the null sample has the exact same distribution of values compared to the original data.
julia
using SpeciesDistributionToolkit
const SDT = SpeciesDistributionToolkit
using CairoMakie
We will get some occurrences from the butterfly Aglais caschmirensis in Pakistan:
julia
pol = getpolygon(PolygonData(NaturalEarth, Countries))["Pakistan"]
presences = GBIF.download("10.15468/dl.emv5tj");
extent = SDT.boundingbox(pol)
(left = 60.84437942504883, right = 77.0489730834961, bottom = 23.69452476501465, top = 37.05448532104492)
And then get some bioclimatic variables:
julia
provider = RasterData(CHELSA2, BioClim)
L = SDMLayer{Float32}[
SDMLayer(
provider;
layer = x,
extent...,
) for x in 1:19
];
mask!(L, pol)
19-element Vector{SDMLayer{Float32}}:
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
🗺️ A 1604 × 1945 layer (1176577 Float32 cells)
As for the previous tutorials, we will generate some background points:
julia
presencelayer = mask(first(L), Occurrences(mask(presences, pol)))
background = pseudoabsencemask(DistanceToEvent, presencelayer)
bgpoints = backgroundpoints(nodata(background, d -> d < 20), 2sum(presencelayer))
🗺️ A 1604 × 1945 layer with 1157282 Bool cells
Projection: +proj=longlat +datum=WGS84 +no_defs
And finally train an ensemble model:
julia
sdm = Bagging(SDM(RawData, DecisionTree, L, presencelayer, bgpoints), 50)
bagfeatures!(sdm)
{RawData → DecisionTree → P(x) ≥ 0.5} × 50
Let's look at the first prediction of this model:
julia
train!(sdm)
heatmap(predict(sdm, L))
lines!(pol)
current_figure()