``` {r eval=T, echo=F, message=F, warning=F}

library(devtools)

install_github("BastilleRousseau/moveNT")

library(moveNT) library(adehabitatLT) library(raster) library(sp) library(ade4) library(adehabitatMA) library(CircStats) library(MASS) library(boot) library(moveHMM) library(mclust) library(igraph) mosaic_network<-function(ls, index=2, sc=T, fun=mean){ layers<-lapply(ls, function(x) x[[index]]) if(sc) {layers<-lapply(layers, scale)} names(layers)[1:2]<-c("x", "y") layers$fun<-fun layers$na.rm<-TRUE layers_mosaic<-do.call(mosaic, layers) return(layers_mosaic) }

# Simulating movement strategies  - *sim_mov*

The function *sim_mov* generates movement trajectories including patches and movement between patches. Movement within patches can follow an Ornstein-Uhlenbeck process (based on *simm.mou* function from package *adehabitatLT*) or two-states movement model (based on *simmData* function from package *moveHMM*). Movement between patches is following a brownian bridge movement model (based on *simm.bb* function from package *adehabitatLT*). Generated outputs are of the class *ltraj* from package *adehabitatlt*.<br> <br>
\newline

``` {r eval=T}
# Simulating migration with two-states model 
mig<-sim_mov(type="2states", npatches=2, ratio=2, nswitch=25, ncore=150, grph=F)
mig
head(ld(mig))
plot(mig)

# Simulating multi-patches movement with Ornstein-Uhlenbeck process 
patches<-sim_mov(nswitch=25, ncore=150, ratio=5, type="OU", npatches=5, grph=T)

# Simulating sedentary movement
seden<-sim_mov(type="OU", npatches=10, spacecore=12, ratio=3, nswitch=150, ncore=20, grph=T)

Converting movement to adjacency matrix - traj2adj

The function traj2adj converts a trajectory object of class ltraj to an adjacency matrix. This is done by overlapping a grid over the relocation data and tallying the number of transitions among each pixel. Users need to specify the grid size, which can be based on distance travelled. The function quant is a wrapper that allows to estimate quantiles of step length distribution from a ltraj object. Output produced by traj2adj is a list containing the adjacency matrix, the grid used (raster format), and a raster indicating pixel numbers that are occupied. These rasters are used by other functions such as adj2stack and clustnet.

\newline

``` {r eval=T}

Using sedentary movement and user specific grid-size

adj_seden<-traj2adj(seden, res=150) #Pixel size of 150m adj_seden[[1]] # Adjency matrix plot(adj_seden[[2]]) #Plot grid used

Using multi-patches movement and median distance travelled

adj_patches<-traj2adj(patches, res=quant(patches, p=0.5)) #Grid size based on median dim(adj_patches[[1]]) # Size of the adjacency matrix plot(adj_patches[[2]]) #Plot grid used plot(adj_patches[[3]]) #Plot occupied pixels

Using user defined grid

ras<-raster(nrows=10, ncols=10, xmn=0, ymn=0, xmx=6000, ymx=6000) adj_patches2<-traj2adj(patches, res=quant(patches, p=0.5), grid=ras) #Grid size based on median plot(adj_patches2[[2]]) #Crop version of the grid created

# Calculation of network metrics  - *adj2stack*

The function *adj2stack* takes the output of function *traj2adj* and calculates a series of node- and graph-level metrics. Each metric is stored as a individual raster and the output is a raster stack combining each metric. Graph-level metrics are also stored as a raster, each containing an unique value. The function *graphmet* extracts graph-level metrics. The function *val* extracts only the occupied cells (remove NA) in a raster and allows the calculation of statistics from node-level metrics. <br> <br>
\newline  

``` {r eval=T}
# Using multi-patches movement and median distance travelled 
stck<-adj2stack(adj_patches, grph=F) #Plot the node-level metrics at the same time 
plot(stck) #Plot also the graph-level metrics (not really useful)
plot(stck[[3]]) #Plot only one metric (degree)
graphmet(stck) # Extract graph-level metrics 
cv(val(stck, 4)) #Extract coefficient of variation of node-level betweenness.  

Clustering of node level metrics - clustnet

The function clustnet applies a normal mixture model to node-level metrics in order to cluster them into separate groups (default = 2). The function takes the output of function adj2stack with the user specifying the metric to cluster and the number of groups. Return a list containing output of function Mclust from package mclust and a raster displaying classification.

\newline

``` {r eval=T}

Using multi-patches movement and median distance travelled

clust2<-clustnet(stck, id=3, nclust=2, grph=F) # Clustering of degree in two groups clust3<-clustnet(stck, id=4, nclust=3, grph=F) #Clustering of betweenness in three groups summary(clust2[[1]]) plot(clust2[[2]]) summary(clust3[[1]]) plot(clust3[[2]])

# Looping over all individuals *loop*

The function *loop* is a wrapper of *traj2adj* and *adj2stack* applied to all individuals within a trajectory. The function will keep the same grid for all individuals. The user simply need to specify the trajectory object and the grid size. The loop function also adds additional movement properties regarding speed, absolute angle, and turning angle. 


``` {r eval=T}
data(albatross) #Load a traj object from adehabitatLT
out1<-loop(albatross, res=35000)
plot(out1[[1]]) #Plot the first individual

Mosaic individual

Even if the the function loop perform the analysis forevery individuals the outputs produced are at the individual-level. The function mosaic_network can combine the different individual levels into a single raster representation. When multiple individuals overlap, the function apply a function (mean or max) to calculate a population-level value for that pixel. To use the function, the user needs to specify which variable to mosaic (using index), whether to scale the individual layers (recommended) and the function to apply. We recommend to use mean for degree and weight and max for the betweenness.

``` {r eval=T} mean_weight<-mosaic_network(out1, index=2, sc=T, fun=mean) #Perform mean weight (not-interpolated)

writeRaster(...

mean_degree<-mosaic_network(out1, index=4, sc=T, fun=mean) #Perform mean weight (not-interpolated)

max_between<-mosaic_network(out1, index=5, sc=T, fun=max) #Perform mean weight (not-interpolated)

par(mfrow=c(1,3)) plot(mean_weight, main="Weight") plot(mean_degree, main="Degree") plot(max_between, main="Betweenness")

# Linear interpolation 
As can be seen in the last plot produced, one of the limitation of the current approach is that it creates gaps in areas where no locations are observed (only pixels with gps locations in them have values). This can sometime limit interpretability or the visual appeal of the maps produced. To assist with this, we created a linear interpolation approach that can be applied at the individual level network calculation (i.e. after *loop*). The interpolation linearly interpolate each step (i.e. straight line) and assign the network metric of each starting location to the whole step. When multiples overlap in a pixel, a function is applied to summarize these steps (e.g. mean or max). This function will take an output from *loop* and performed the interpolation for five metrics (weight, degree, betweenness, speed, and turning angles). We recommend to take the mean for weight, degree, betweenness, and speed, the max for betweenness, and the dot-product for the turning angles (default).   

``` {r eval=T}
data(albatross) #Load a traj object from adehabitatLT
out1<-loop(albatross, res=35000)
out2<-interpolation(albatross, out1) #This is very slow, more than 5 minutes
mean_mean_degree<-mosaic_network(out2, index=2, sc=T, fun=mean)
max_max_between<-mosaic_network(out2, index=3, sc=T, fun=max)
mean_mean_speed<-mosaic_network(out2, index=4, sc=T, fun=mean)
mean_dot_TA<-mosaic_network(out2, index=5, sc=T, fun=mean)
par(mfrow=c(2,2))
plot(mean_mean_degree, main= "Degree")
plot(max_max_between, main="Betweenness")
plot(mean_mean_speed, main="Speed")
plot(mean_dot_TA, main="Directionality")


BastilleRousseau/moveNT documentation built on Aug. 26, 2023, 5:54 a.m.