Skip to content

Convex hull fundamental niche model

tretherington edited this page Sep 21, 2020 · 12 revisions

One common ecological application of a convex hull is the modelling of the fundamental niche of a species. To demonstrate how compGeometeR can be used in conjunction with R packages to perform such an analysis the following is an extremely simple example for modelling the fundamental niche of the European hedgehog (Erinaceus europaeus).

We can get data on where hedgehogs are known to occur from the Global Biodiversity Information Facility and climate data from WorldClim. By plotting the hedgehog occurrences on top of the mean annual temperature and annual rainfall climate maps we can get an immediate sense that these hedgehogs are a temperate species.

By extracting the climatic data at the occurrence locations and plotting these in environmental space we can get a sample of the climatic conditions that are suitable for this species, and by using compGeometeR's convex_hull function we can create a convex hull around the occurrences an estimate of the species' fundamental niche can be made.

Having defined the convex hull, using compGeometeR's in_convex_hull function the climatic conditions for all locations on the planet can be compared to the convex hull to see if the conditions are within the fundamental niche or not. When mapped out we can then get a sense of where the European hedgehog could exist. Europe is the natural range of the species, so it is not surprising that the climatic conditions are suitable here, but we can also see that the conditions in New Zealand where the hedgehog is an invasive species are unfortunately also suitable. There are also many other parts of the world that are climatically suitable if it were to invade there too, so it is very sensible that countries like Australia do not allow hedgehogs to be brought into the country.

The following script puts that whole process together, and reproduces the figures above:

#-------------------------------------------------------------------------------

# R version 3.5.3 (2019-03-11) -- "Great Truth"
# Platform: x86_64-w64-mingw32/x64 (64-bit)
library(compGeometeR) # version 1.0
library(raster) # version 2.9-5
library(rgbif) # version 1.3.0

#-------------------------------------------------------------------------------

# Download occurrence data from GBIF (https://www.gbif.org/)
hedgehog = occ_data(scientificName = "Erinaceus europaeus", hasCoordinate=TRUE)
hedgehogCoords = hedgehog$data[,c("decimalLongitude", "decimalLatitude")]

#-------------------------------------------------------------------------------

# Download bioclimate data from WorldClim (https://www.worldclim.org/)
bioclim = getData('worldclim', var='bio', res=10)
mean_annual_temperature = bioclim[[1]] / 10 # divide by 10 to adjust units
total_annual_rainfall = bioclim[[12]]
plot(mean_annual_temperature, col=colorRampPalette(c("pink", "firebrick"))(10),
     main=expression(paste("Mean annual temperature (", degree, "C)")))
points(hedgehogCoords, pch=16, cex=0.5)
legend("bottomleft", legend=c("Hedgehog occurrence"), pch=16, bty="n", pt.cex=0.5)
plot(total_annual_rainfall, col=colorRampPalette(c("skyblue", "darkblue"))(10),
     main="Annual rainfall (mm)")
points(hedgehogCoords, pch=16, cex=0.5)
legend("bottomleft", legend=c("Hedgehog occurrence"), pch=16, bty="n", pt.cex=0.5)

#-------------------------------------------------------------------------------

# Extract the climate data for each location
tempData = extract(mean_annual_temperature, hedgehogCoords)
rainData = extract(total_annual_rainfall, hedgehogCoords)
hedgehogData = cbind(hedgehogCoords, tempData, rainData)

# Create the fundamental niche as a convex hull
fundNiche = convex_hull(hedgehogData[,c("tempData", "rainData")])

# Plot the fundamental niche
plot(hedgehogData[,c("tempData", "rainData")], pch=16,
     xlim=c(0,20), ylim=c(0,3500),
     xlab=expression(paste("Mean annual temperature (", degree, "C)")), 
     ylab="Annual rainfall (mm)", las=1, bty="n",
     main="Hedgehog fundamental niche model in environmental space")
for (s in seq(nrow(fundNiche$hull_simplices))) {
  lines(fundNiche$input_points[fundNiche$hull_simplices[s, ], ], col = "red")
}
legend("topleft", legend=c("Hedgehog occurrence"), pch=16, bty="n")
legend("topright", legend=c("Fundamental niche"), col="red", lwd=1, bty="n")

#-------------------------------------------------------------------------------

# Determine which global climate values are within the fundamental niche
tempRasterValues = getValues(mean_annual_temperature)
rainRasterValues = getValues(total_annual_rainfall)
globalClimate = as.data.frame(cbind(tempRasterValues, rainRasterValues))
nicheValues = in_convex_hull(fundNiche, globalClimate)

# Create new global raster and apply niche values
globalNiche = mean_annual_temperature
values(globalNiche) = nicheValues

# Plot prediction and occurrences
plot(globalNiche, col=colorRampPalette(c("grey", "red"))(2),
     main="Hedgehog fundamental niche model in geographic space")
points(hedgehogCoords, pch=16, cex=0.5)
legend("bottomleft", legend=c("Hedgehog occurrence"), pch=16, bty="n", pt.cex=0.5)

#-------------------------------------------------------------------------------
Clone this wiki locally