2024-02-21

Connectivity

Why Connectivity

  • Fragmentation is one of the main drivers of biodiversity loss
  • It diminishes genetic diversity

Continuous connectivity measures

Geographic vs continuous connectivity

RasterMaps <- terra::rast(system.file("extdata/covariates.tif", package = "GeNetIt"))
data(ralu.site, package = "GeNetIt")
sites <- ralu.site

Variables

Rasters:

  • cti: Compound Topographic Index (“wetness”)
  • err27: Elevation Relief Ratio
  • ffp: Frost Free Period
  • gsp: Growing Season Precipitation
  • hli: Heat Load Index
  • nlcd: USGS Landcover (categorical map)

Conductance in gDistance

Ranked by experts ordinal 1) cti, 2) gsp, 3) ffp, 4) err27

  • err27: The elevation relief ratio identifies significant topographic features, higher ERR27 indicate greater topographic change ~ increased resistance. has to be inverted
  • ffp frost free preriod, the higher the value the more conductivity
  • gsp Growing Season Precipitation, it has to be more than 196 mm for key species to be present
  • cti Compound Topographic Index, the higher the more conductivity
err.cost <- (1/RasterMaps[["err27"]])
ffp.cost <- (RasterMaps[["ffp"]]/5)
gsp.cost <- (RasterMaps[["gsp"]] - 196)/15
cti.cost <- RasterMaps[["cti"]]/5
cost1 <- (gsp.cost + cti.cost + err.cost + ffp.cost)

conductance and sampling points

Generating transition matrices

tr.cost1 <- gdistance::transition(raster::raster(cost1), transitionFunction = mean,
    directions = 8)
tr.cost1 <- gdistance::geoCorrection(tr.cost1, type = "c", multpl = FALSE)

Geographic path

Neighbours <- terra::delaunay(vect(sites), as.lines = T)

Add least cost

Lines <- list()

for (i in 1:nrow(Neighbours)) {
    Temp <- as.matrix(as.data.frame(terra::intersect(terra::vect(sites), Neighbours[i,
        ]), geom = "XY")[c("x", "y")])
    Lines[[i]] <- terra::vect(sf::st_as_sf(gdistance::shortestPath(tr.cost1, origin = Temp[1,
        ], goal = Temp[2, ], output = "SpatialLines")))
    terra::crs(Lines[[i]]) <- terra::crs(Neighbours)
}

Lines <- Lines |>
    purrr::reduce(rbind)

Add least cost (Plot)

Distance Correlation

Actual cost

Temp <- as.matrix(as.data.frame(terra::vect(sites), geom = "XY")[c("x", "y")])

DF1 <- GeNetIt::dmatrix.df(as.matrix(gdistance::costDistance(tr.cost1, Temp))) |>
    dplyr::rename(least_cost = distance)

DF2 <- GeNetIt::dmatrix.df(as.matrix(gdistance::commuteDistance(tr.cost1, Temp))) |>
    dplyr::rename(commute_time = distance)

DF3 <- GeNetIt::dmatrix.df(as.matrix(distance(terra::vect(sites)))) |>
    dplyr::rename(euclidean_dist = distance)


DF4 <- read.csv("https://raw.githubusercontent.com/Sustainscapes/Sustainscapes.github.io/master/SpatialContinuity/data/gdist.csv",
    header = TRUE) |>
    dplyr::rename(from = FROM, to = TO, genetic_dist = GDIST) |>
    dplyr::select(from, to, genetic_dist)

DF <- list(DF1, DF2, DF3, DF4) |>
    purrr::reduce(full_join)

Comparison

Comparison 2

Exercise

Check connectivity in Denmark

data("Landuse_DK")
Landuse <- terra::unwrap(Landuse_DK)
## Make sourcers to be dry nature
DryNature <- Landuse

DryNature <- terra::ifel(DryNature == "dry nature", 1, NA)

Patches <- terra::aggregate(DryNature, by = "Landuse") |>
    as.polygons() |>
    disagg()
## 
|---------|---------|---------|---------|
=========================================
                                          
Patches$Area_ha <- terra::expanse(Patches, unit = "ha")

Centroids <- terra::centroids(Patches)

Centroids_DF <- as.data.frame(Centroids, geom = "XY")

Generate new landuse types

CLS1 <- levels(Landuse)[[1]]

NewCls <- data.frame(ID = c(0, 1), Type = c("Non-nature", "Nature"))

Nature <- as.numeric(Landuse)

Nature <- terra::ifel(Nature %in% c(7, 8, 11), 1, 0)

Nature <- mask(Nature, Landuse)

levels(Nature) <- NewCls

Exercise

  • Choose on of the new maps (DryNature, Nature)
  • Choose one of the Landuses in Landuse, and check for different radiuses and generate habitat continuities using SpatioTemporalCont::calculate_prop
  • Calculate commuteDistance and costDistance to compare with euclidean distance with the different options

Lets work for 15 mins

Graph based connectivity measures

How does it work

  • We generate a network of patches
  • Each patch has attributes (Size, Diversity, Land use, etc)
  • Each edge has attributes (Distance, conductivity/resistance)

Pros and cons

Pros

  • Computationally eficient
  • Robust mathematical framework

Cons

  • Generating the dataset as a network might not be as easy
  • Networks are less intuitive

How to build your network

library(sfnetworks)
Patches$ID <- 1:nrow(Patches)
Centroids$ID <- 1:nrow(Centroids)
Centroids_SF <- sf::st_as_sf(Centroids)
# Patches connected to 2000 meters
joins <- nearby(Patches, distance = 2000) |>
    as.data.frame()


Edges <- purrr::map(1:nrow(joins), ~as.lines(rbind(Centroids[Centroids$ID == joins$from[.x],
    ], Centroids[Centroids$ID == joins$to[.x], ]))) |>
    purrr::reduce(rbind)

Edges$from <- joins$from
Edges$to <- joins$to

net <- sfnetworks::sfnetwork(nodes = Centroids_SF, edges = sf::st_as_sf(Edges))

Plot edges

Plot Network

Several distances

Network flow

Networks through time

  • Changes in suitability through time

Networks through time

  • As a network

Changing the dispersal

Solving for 2 chains

Graph solution

Geographic representation