# testNM {adehabitatLT}

### Description

The functions `NMs.*`

allow to define "single null models" (see details). The function `NMs2NMm`

can be used on an object of class `"NMs"`

to define "multiple null models". The function `testNM`

can be used to simulate the defined null models.

### Usage

NMs.randomCRW(ltraj, rangles = TRUE, rdist = TRUE, fixedStart = TRUE, x0 = NULL, rx = NULL, ry = NULL, treatment.func = NULL, treatment.par = NULL, constraint.func = NULL, constraint.par = NULL, nrep = 999) NMs.randomShiftRotation(ltraj, rshift = TRUE, rrot = TRUE, rx = NULL, ry = NULL, treatment.func = NULL, treatment.par = NULL, constraint.func = NULL, constraint.par = NULL, nrep = 999) NMs.CRW(N = 1, nlocs = 100, rho = 0, h = 1, x0 = c(0,0), treatment.func = NULL, treatment.par = NULL, constraint.func = NULL, constraint.par = NULL, nrep = 999) NMs.randomCs(ltraj, Cs = NULL, rDistCs = TRUE, rAngleCs = TRUE, rCentroidAngle = TRUE, rCs = TRUE, newCs = NULL, newDistances = NULL, treatment.func = NULL, treatment.par = NULL, constraint.func = NULL, constraint.par = NULL, nrep=999) NMs2NMm(NMs, treatment.func = NULL, treatment.par = NULL, constraint.func = NULL, constraint.par = NULL, nrep = 999) ## S3 method for class 'NMm': print((x, ...)) ## S3 method for class 'NMs': print((x, ...) testNM(NM, count = TRUE))

### Arguments

- ltraj
- an object of class
`"ltraj"`

- rangles
- logical. Whether the turning angles should be randomized.
- rdist
- logical. Whether the distances between successive relocations should be randomized.
- fixedStart
- logical. If
`TRUE`

, the first location of the randomized trajectories corresponds to`x0`

. If`FALSE`

, the first location`(x, y)`

is sampled in the interval`(rx, ry)`

- x0
- a vector of length 2 giving the x and y coordinates of the first relocations. If
`NULL`

and`fixedStart=TRUE`

, the first location of the trajectory corresponds to the first location of the actual trajectory - rx
- a vector of length 2 giving the x coordinates of the bounding box where the first location of the trajectory should be sampled
- ry
- a vector of length 2 giving the range (min, max) of the y coordinates of the bounding box where the first location of the trajectory should be sampled
- treatment.func
- any function taking two arguments
`x`

and`par`

, where`x`

is the trajectory generated by the function, and par can be any R object (e.g. a list containing the parameters needed by the function. Note that the argument`par`

should be present in the function definition even if it is not needed in the function). See details and examples. If`NULL`

, a function is defined internally that simply returns the raw trajectory simulated by the model - treatment.par
- the R object that will be passed as an argument to the parameter
`par`

of the function`treatment.func`

- constraint.func
- any function taking two arguments
`x`

and`par`

, where`x`

is the trajectory generated by the function, and par can be any R object (e.g. a list containing the parameters needed by the function). **This function should necessarily return a logical value** (See details and examples). If`NULL`

, a function is defined internally that always returns`TRUE`

- constraint.par
- The R object that will be passed as an argument to the parameter
`par`

of the function`constraint.func`

- nrep
- The number of repetitions of the null model
- rshift
- logical. Whether the trajectory should be shifted over the study area.
- rrot
- logical. Whether the trajectory should be rotated around its barycentre.
- N
- The number of animals to simulate.
- nlocs
- The number of relocations building up each trajectory
- rho
- The concentration parameter for wrapped normal distribution of turning angles (see
`?simm.crw`

) - h
- the scaling parameter for the movement length (see
`?simm.crw`

) - Cs
- a list of vectors of length 2. Each vector should contain the x and y coordinates of the capture sites of the animals in
`ltraj`

. This list should therefore have the same number of elements as`ltraj`

- rDistCs
- logical. Whether the distances between the barycentre of the trajectories and the corresponding capture sites should be randomized among trajectories
- rAngleCs
- logical. Whether the angle between the east direction and the line connecting the capture site and the barycentre of the trajectory should be drawn from an uniform distribution.
- rCentroidAngle
- logical. Whether the trajectory should be randomly rotated around its barycentre.
- rCs
- logical. Whether the trajectory should be randomly associated to a new capture site.
- newCs
- a list of vectors of length 2. Each vector should contain the x and y coordinates of new capture sites. If
`NULL`

and`rcs=TRUE`

, the new capture sites are sampled in`cs`

- newDistances
- a vector of new distances that will be used to define the distances between capture sites and centroid of simulated trajectories if
`rDistCs=TRUE`

- NM,x
- a null model of class
`"NMs"`

or`"NMm"`

- NMs
- a null model of class
`"NMs"`

- count
- whether the iterations should be displayed
- ...
- additionnal arguments to be passed to or from other methods

### Details

The null model approach has been considered as a useful approach in many fields of ecology to study biological processes. According to Gotelli and Graves (1996), "A null model is a pattern-generating model that is based on randomization of ecological data or random sampling from a known or imagined distribution. The null model is designed with respect to some ecological or evolutionary process of interest. Certain elements of the data are held constant, and others are allowed to vary stochastically to create new assemblage patterns. The randomization is designed to produce a pattern that would be expected in the absence of a particular ecological mechanism".

This approach can be very useful to test hypotheses related to animal movements. The package adehabitatLT propose several general null models that can be used to test biological hypotheses. For example, imagine that we want to test the hypothesis that no habitat selection occurs when the animal moves. The shape of the trajectory, under this hypothesis would be the pure result of changing activity (moving, foraging, resting). Therefore, a possible approach to test whether habitat selection actually occurs would be to randomly rotate the trajectory around its barycentre and shifting it over the study area. The function `NMs.randomShiftRotation`

can be used to define such a model. It is possible to constrain the randomization by defining a "constraint function" (e.g. to keep only the randomized trajectories satisfying a given criterion). It is required to specify a "treatment function" (i.e., a function that will be applied to each randomized trajectory). Once the null model has been defined, it is then possible to perform the randomizations using the function `testNM`

. We give below the details concerning the available null models, as well as the constraint and the treatment functions.

First, two types of null models can be defined: single (NMs) and multiple (NMm) null models. Consider an object of class `"ltraj"`

containing `N`

bursts. With NMs, the treatment function will be applied to each randomized burst of relocations. Thus, for example, if `nrep`

repetitions of the null model are required, `nrep`

repetitions of the null models will be carried out for each burst separately. The treatment function will be applied on each randomized burst. With NMm, for each repetition, `N`

randomized bursts of relocations are generated. The treatment is then applied, for each repetition, to the whole set of `N`

randomized bursts. Thus, `NMs`

are useful to test hypothesis on each trajectory separately (e.g. individual habitat selection), whereas `NMm`

are useful to test hypotheses relative to the whole set of animals stored in an object of class `ltraj`

(e.g. interactions between animals). The only current way to define an object of class `NMm`

is to first define an object of class `NMs`

and then use the function `NMs2NMm`

to indicate the treatment function that should be applied on the whole set of trajectories.

The constraint function should be user-defined. It should return a logical value indicating whether the constraint is satisfied. With `NMs`

, this function should take only two parameters: `x`

and `par`

. The argument `x`

is a data frame with three columns describing a trajectory (the X and Y coordinates, and the date as a vector of class `"POSIXct"`

), and the argument `par`

can be any R object required by the constraint function (e.g. if the constraint to keep 80% of the relocations of the randomized trajectories within a given habitat type, the parameter `par`

can be a raster map, or a list of raster maps). With `NMm`

, this function should also take only the two parameters `x`

and `par`

. The argument `par`

can be any R object required by the constraint function. However, when `"NMm"`

are defined, the argument `x`

of the constraint function should be an object of class `"ltraj"`

. If the function `NMs2NMm`

is used to define the object of class `"NMm"`

, two types of constraint can therefore be defined: at the individual level (in the function `NMs.*`

) and for the whole set of animals (in the function `NMs2NMm`

). In this case, some constraints will be satisfied at the individual level, and others at the scale of the whole set of animals. If no constraint function is defined by the user, a constraint function always returning `TRUE`

is automatically defined internally.

The treatment function can be any function defined by the user, but should take two arguments `x`

and `par`

, identical to those passed to the constraint function (i.e., `x`

should be a data frame with three columns for `NMs`

and an object of class `"ltraj"`

for `NMm`

. Note that only one treatment function can be applied to the randomization: if `NMs2NMm`

is used to define an object of class `NMm`

, the treatment function defined in the function `NMs.*`

will be ignored, and only the treatment function defined in the function `NMs2NMm`

will be taken into account. If no treatment function is defined by the user, a treatment function will be defined internally, simply returning the randomized trajectory (i.e. a data.frame with three columns for `NMs`

, and an object of class `ltraj`

for `NMm`

). We now describe the list of available null models: `NMs.CRW`

: this model is a purely parametric model. It simulates a correlated random walk with specified parameters (see `?simm.crw`

for a complete description of this model). `NMs.randomCRW`

: this model also simulates a correlated random walk, but the distributions of the turning angles and/or distances between successive relocations are derived from the trajectories passed as arguments. It is possible to randomize the turning angles, the distances between successive relocations, or both (default). `NMs.randomShiftRotation`

: this model randomly rotates the trajectory around its barycentre and randomly shifts it over the study area (but does not change its shape). The function allows for a random rotation, a random shift or both operations (default). `NMs.randomCs`

: this model is similar to the previous one: it keeps the shape of the trajectory unchanged. However, it randomizes the position of the trajectories with respect to a set of capture sites (it can be used to take into account the fact that a the home range of a sedentary animal captured at a given place is likely to be close to this place). First a capture site may be randomly drawn from a list of capture sites (either the actual capture sites or a list passed by the user). Then, the angle between the east direction and the line connecting the capture site of the animal and the barycentre of its trajectory is randomly drawn from a uniform distribution. Then, the distance between this barycentre and the capture site is randomly drawn from the observed distribution of distances between capture sites and trajectory barycentre (or from a set of distances passed as argument). Finally, the trajectory is randomly rotated around its barycentre.

### Values

For objects of class `"NMs"`

a list of `N`

elements (where `N`

is the number of trajectories in the object of class `"ltraj"`

passed as argument, with each element is a list storing the `nrep`

results of the treatment function applied to each randomized trajectory.

For objects of class `"NMm"`

, a list of `nrep`

elements, each element storing the result of the treatment function applied to each set of `N`

randomized trajectories.

### References

Gotelli, N. and Graves, G. (1996) *Null models in Ecology*. Smithsonian Institution Press.

Richard, E., Calenge, C., Said, S., Hamann, J.L. and Gaillard, J.M. (2012) Studying spatial interactions between sympatric populations of large herbivores: a null model approach. *Ecography*, in press.

### See Also

`as.ltraj`

for additional information about objects of class `"ltraj"`

### Examples

######################################## ## ## example using NMs.randomShiftRotation ## first load the data: data(puechcirc) data(puechabonsp) map <- puechabonsp$map ## Consider the first animal ## on an elevation map anim1 <- puechcirc[1] plot(anim1, spixdf=map[,1]) ## We define a very simple treatment function ## for a NMs model: it just plots the randomized trajectory ## over the study area ## As required, the function takes two arguments: ## x is a data.frame storing a randomized trajectory (three ## columns: the x, y coordinates and the date) ## par contains the map of the study area myfunc <- function(x, par) { par(mar = c(0,0,0,0)) ## first plot the map image(par) ## then add the trajectory lines(x[,1], x[,2], lwd=2) } ## Then we define the null model ## ## We define the range of the study area where the trajectory ## will be shifted: rxy <- apply(coordinates(map),2,range) rxy ## We define the null model with 9 repetitions nmo <- NMs.randomShiftRotation(na.omit(anim1), rshift = TRUE, rrot = TRUE, rx = rxy[,1], ry = rxy[,2], treatment.func = myfunc, treatment.par = map, nrep=9) ## Then apply the null model par(mfrow = c(3,3)) tmp <- testNM(nmo) ## You may try variations, by setting rshift or rrot to FALSE, to see ## the differences ## Note that some of the randomized trajectories are located outside the ## study area, although all barycentres are located within the X and Y ## limits of this study area. ## We may define a constraint function returning TRUE only if all ## relocations are located within the study area ## again, note that the two parameters are x and par consfun <- function(x, par) { ## first convert x to the class SpatialPointsDataFrame coordinates(x) <- x[,1:2] ## then use the function over from the package sp ## to check whether all points in x are located inside ## the study area ov <- over(x, geometry(map)) return(all(!is.na(ov))) } ## Now fit again the null model under these constraints: nmo2 <- NMs.randomShiftRotation(na.omit(anim1), rshift = TRUE, rrot = TRUE, rx = rxy[,1], ry = rxy[,2], treatment.func = myfunc, treatment.par = map, constraint.func = consfun, constraint.par = map, nrep=9) ## Then apply the null model par(mfrow = c(3,3)) tmp <- testNM(nmo2) ## all the relocations are now inside the study area. ######################################## ## ## example using NMs.randomCRW ## We generate correlated random walks with the same starting ## point as the original trajectory, the same turning angle ## distribution, and the same distance between relocation ## distribution. We use the same constraint function as previously ## (all relocations falling within the study area), and we ## use the same treatment function as previously (just plot ## the result). mo <- NMs.randomCRW(na.omit(anim1), rangles=TRUE, rdist=TRUE, treatment.func = myfunc, treatment.par = map, constraint.func=consfun, constraint.par = map, nrep=9) par(mfrow = c(3,3)) tmp <- testNM(mo) ## Not run: ## Now, try a different treatment function: e.g. measure ## the distance between the first and last relocation, ## to test whether the animal is performing a return trip myfunc2 <- function(x, par) { sqrt(sum(unlist(x[1,1:2] - x[nrow(x),1:2])^2)) } ## Now fit again the null model with this new treatment and 499 repetitions: mo2 <- NMs.randomCRW(na.omit(anim1), rangles=TRUE, rdist=TRUE, treatment.func = myfunc2, treatment.par = map, constraint.func=consfun, constraint.par = map, nrep=499) ## Then apply the null model set.seed(298) ## to make the calculation reproducible rand <- testNM(mo2) ## rand is a list with one element (there is one trajectory in anim1). length(rand[[1]]) ## The first element of rand is a list of length 499 (there are 499 ## randomizations). head(rand[[1]]) ## unlist this list: rand2 <- unlist(rand[[1]]) ## calculate the observed average elevation: obs <- myfunc2(na.omit(anim1)[[1]][,1:3], map) ## and performs a randomization test: (rt <- as.randtest(rand2, obs, alter="less")) plot(rt) ## Comparing to a model where the animal is moving randomly, and based ## on the chosen criterion (distance between the first and last ## relocation), we can see that the distance between the first and last ## relocation is rarely observed. It seems to indicate that the animal ## tends to perform a loop. ######################################## ## ## example using NMs2NMm ## Given the previous results, we may try to see if all ## the trajectories in puechcirc are characterized by return ## trips ## We need a NMm approach. Because we have 3 burst in puechcirc ## we need a summary criterion. For example, the mean ## distance between the first and last relocation. ## We program a treatment function: it also takes two arguments, but x ## is now an object of class "ltraj" ! ## par is needed, but will not be used in the function myfunm <- function(x, par) { di <- unlist(lapply(x, function(y) { sqrt(sum(unlist(y[1,1:2] - y[nrow(y),1:2])^2)) })) return(mean(di)) } ## Now, prepare the NMs object: we do not indicate any treatment ## function (it would not be taken into account when NMs would be ## transformed to NMm). However, we keep the constraint function ## the simulated trajectories should fall within the study area mo2s <- NMs.randomCRW(na.omit(puechcirc), constraint.func=consfun, constraint.par = map) ## We convert this object to NMm, and we pass the treatment function mo2m <- NMs2NMm(mo2s, treatment.func = myfunm, nrep=499) ## and we fit the model set.seed(908) resu <- testNM(mo2m) ## We calculate the observed mean distance between the ## first and last relocation obs <- myfunm(na.omit(puechcirc)) ## and performs a randomization test: (rt <- as.randtest(unlist(resu), obs, alter="less")) plot(rt) ## The test is no longer significant ## End(Not run) ######################################## ## ## example using NMs.randomCs ## Consider this sample of 5 capture sites: cs <- list(c(701184, 3161020), c(700164, 3160473), c(698797, 3159908), c(699034, 3158559), c(701020, 3159489)) image(map) lapply(cs, function(x) points(x[1], x[2], pch=16)) ## Consider this sample of distances: dist <- c(100, 200, 150) ## change the treatment function so that the capture sites are showed as ## well. Now, par is a list with two elements: the first one is the map ## and the second one is the list of capture sites myfunc <- function(x, par) { par(mar = c(0,0,0,0)) ## first plot the map image(par[[1]]) lapply(par[[2]], function(x) points(x[1], x[2], pch=16)) ## then add the trajectory lines(x[,1], x[,2], lwd=2) } ## Now define the null model, with the same constraints ## and treatment as before mod <- NMs.randomCs(na.omit(anim1), newCs=cs, newDistances=dist, treatment.func=myfunc, treatment.par=list(map, cs), constraint.func=consfun, constraint.par=map, nrep=9) ## apply the null model par(mfrow = c(3,3)) tmp <- testNM(mod)

Documentation reproduced from package adehabitatLT, version 0.3.14. License: GPL (>= 2)