sim.popn: Simulate 2-D Population

sim.popnR Documentation

Simulate 2-D Population

Description

Simulate a point process representing the locations of individual animals.

Usage


sim.popn (D, core, buffer = 100, model2D = c("poisson", "cluster",
  "IHP", "coastal", "hills", "linear", "even", "rLGCP", "rThomas"), 
  buffertype = c("rect", "concave", "convex"), poly = NULL, 
  covariates = list(sex = c(M = 0.5, F = 0.5)), number.from = 1, 
  Ndist = c("poisson", "fixed", "specified"), nsessions = 1, details = NULL, 
  seed = NULL, keep.mask = model2D %in% c("IHP", "linear"), 
  Nbuffer = NULL, age = FALSE, ...)

tile(popn, method = "reflect")

Arguments

D

density animals / hectare (10 000 m^2) (see Details for IHP case)

core

data frame of points defining the core area

buffer

buffer radius about core area

model2D

character string for 2-D distribution

buffertype

character string for buffer type

poly

bounding polygon (see Details)

covariates

list of named covariates

number.from

integer ID for animal

Ndist

character string for distribution of number of individuals

nsessions

number of sessions to simulate

details

optional list with additional parameters

seed

either NULL or an integer that will be used in a call to set.seed

keep.mask

logical; if TRUE and model2D %in% c('IHP','linear') then core is saved as the attribute "mask"

Nbuffer

integer number of individuals to simulate

age

logical; if TRUE then age covariate added for multisession popn with turnover

...

arguments passed to subset if poly is not NULL

popn

popn object

method

character string "reflect" or "copy"

Details

core must contain columns ‘x’ and ‘y’; a traps object is suitable. For buffertype = "rect", animals are simulated in the rectangular area obtained by extending the bounding box of core by buffer metres to top and bottom, left and right. This box has area A. If model2D = 'poisson' the buffer type may also be ‘convex’ (points within a buffered convex polygon) or ‘concave’ (corresponding to a mask of type ‘trapbuffer’); these buffer types use buffer.contour.

A notional random covariate ‘sex’ is generated by default.

Each element of covariates defines a categorical (factor) covariate with the given probabilities of membership in each class. No mechanism is provided for generating continuous covariates, but these may be added later (see Examples).

Ndist should usually be ‘poisson’ or ‘fixed’. The number of individuals N has expected value DA. If DA is non-integer then Ndist = "fixed" results in N \in \{ \mathrm{trunc}(DA), \mathrm{trunc}(DA)+1 \} , with probabilities set to yield DA individuals on average. The option ‘specified’ is undocumented; it is used in some open-population simulations.

If model2D = "cluster" then the simulated population approximates a Neyman-Scott clustered Poisson distribution. Ancillary parameters are passed as components of details: details$mu is the expected number of individuals per cluster and details$hsigma is the spatial scale (\sigma) of a 2-D kernel for location within each cluster. The algorithm is

  1. Determine the number of clusters (parents) as a random Poisson variate with \lambda = DA/\mu

  2. Locate each parent by drawing uniform random x- and y-coordinates

  3. Determine number of offspring for each parent by drawing from a Poisson distribution with mean mu

  4. Locate offspring by adding random normal error to each parent coordinate

  5. Apply toroidal wrapping to ensure all offspring locations are inside the buffered area

A special cluster option is selected if details$clone = "constant": then each parent is cloned exactly details$mu times.

Toroidal wrapping is a compromise. The result is more faithful to the Neyman-Scott distribution if the buffer is large enough that only a small proportion of the points are wrapped.

If model2D = "IHP" then an inhomogeneous Poisson distribution is simulated. core should be a habitat mask and D should be one of –

  • a vector of length equal to the number of cells (rows) in core,

  • the name of a covariate in core that contains cell-specific densities (animals / hectare),

  • a function to generate the intensity of the distribution at each mask point, or

  • a constant.

If a function, D should take two arguments, a habitat mask and a list of parameter values ('core' and 'details' are passed internally as these arguments).

The number of individuals in each cell is either (i) Poisson-distributed with mean DA where A is the cell area (an attribute of the mask) (Ndist = "poisson") or (ii) multinomial with size DA and relative cell probabilities given by D (Ndist = "fixed"). buffertype and buffer are ignored, as the extent of the population is governed entirely by the mask in core.

If model2D = "linear" then a linear population is simulated as for model2D = "IHP", except that core should be a linearmask object from package secrlinear, and density (D) is expressed in animals per km. The documentation of secrlinear should be consulted for further detail (e.g. the wrapper function sim.linearpopn).

If model2D = "coastal" then a form of inhomogeneous Poisson distribution is simulated in which the x- and y-coordinates are drawn from independent Beta distributions. Default parameters generate the ‘coastal’ distribution used by Fewster and Buckland (2004) for simulations of line-transect distance sampling (x ~ Beta(1, 1.5), y ~ Beta(5, 1), which places 50% of the population in the ‘northern’ 13% of the rectangle). The four Beta parameters may be supplied in the vector component Beta of the ‘details’ list (see Examples). The Beta parameters (1,1) give a uniform distribution. Coordinates are scaled to fit the limits of a sampled rectangle, so this method assumes buffertype = "rect".

If model2D = "hills" then a form of inhomogeneous Poisson distribution is simulated in which intensity is a sine curve in the x- and y- directions (density varies symmetrically between 0 and 2 x D along each axis). The number of hills in each direction (default 1) is determined by the ‘hills’ component of the ‘details’ list (e.g. details = list(hills=c(2,3)) for 6 hills). If either number is negative then alternate rows will be offset by half a hill. Displacements of the entire pattern to the right and top are indicated by further elements of the ‘hills’ component (e.g. details = list(hills=c(1,1,0.5,0.5)) for 1 hill shifted half a unit to the top right; coordinates are wrapped, so the effect is to split the hill into the four corners). Negative displacements are replaced by runif(1). Density is zero at the edge when the displacement vector is (0,0) and rows are not offset.

If model2D = "even" then the buffered area is divided into square cells with side sqrt(10000/D) and one animal is located at a random uniform location within each cell. If the height or width is not an exact multiple of the cell side then one whole extra row or column of cells is added; animals located at random in these cells are discarded if they fall outside the original area.

From secr 4.6.2, sim.popn provides an interface to two simulation functions from spatstat (Baddeley et al. 2015): rLGCP and rThomas.

If model2D = "rLGCP" then a log-gaussian Cox process is simulated within the buffered area. Function rLGCP in spatstat calls functions from RandomFields (Schlather et al. 2015; see Notes). Certain options are fixed: the correlation function is RMexp from RandomFields, and there is no provision for covariate effects. Clipping to a polygon (poly) and fixed-N (Ndist = "fixed") are not supported. The algorithm first constructs the log spatial intensity as a realisation of a Gaussian random field; one realisation of an IHP with that intensity is then simulated.

The parameters for model2D = "rLGCP" are the scalar density (D) and the variance and spatial scale of the random field (passed as details arguments ‘var’ and ‘scale’). The variance is on the log scale; the mean on the log scale is computed internally as mu = log(D) - var/2. var = 0 results in a random uniform (Poisson) distribution. The discretized intensity function is saved as the attribute "Lambda", a habitat mask with covariate "Lambda" that may be used to construct further IHP realisations (see Examples).

If model2D = "rThomas" then a Thomas process is simulated. This is a special case of the Neyman-Scott process in which each parent gives rise to a Poisson number of offspring (see Notes). The expected number of offspring per parent and the spatial scatter about each parent are specified by the details arguments ‘mu’ and ‘scale’. Argument ‘kappa’ of rThomas (density of parent process) is computed as D/mu/1e4. Other arguments remain at their defaults, including ‘expand’ (4 * scale).

If poly is specified, points outside poly are dropped. poly may be one of the types descrbed in boundarytoSF.

The subset method is called internally when poly is used; the ... argument may be used to pass values for keep.poly and poly.habitat.

Multi-session populations may be generated with nsessions > 1. Multi-session populations may be independent or generated by per capita turnover from a starting population. In the ‘independent’ case (details$lambda not specified) D or Nbuffer may be a vector of length equal to nsessions. Turnover is controlled by survival, growth rate and movement parameters provided as components of details and described in turnover. The optional covariate 'age' is the number of sessions from the session of recruitment.

The random number seed is managed as in simulate.lm.

Function tile replicates a popn pattern by either reflecting or copying and translating it to fill a 3 x 3 grid.

Value

An object of class c("popn", "data.frame") a data frame with columns ‘x’ and ‘y’. Rows correspond to individuals. Individual covariates (optional) are stored as a data frame attribute. The initial state of the R random number generator is stored in the ‘seed’ attribute.

If model2D = "linear" the output is of class c("linearpopn", "popn", "data.frame").

If model2D = "IHP" or model2D = "linear" the value of core is stored in the ‘mask’ attribute.

Notes

Package RandomFields is not currently on CRAN. It may be installed with this code:

install.packages("RandomFields", repos = c("https://spatstat.r-universe.dev", "https://cloud.r-project.org"))

model2D = "rThomas" and model2D = "cluster" (the builtin Neyman-Scott implementation) are equivalent. There may be some subtle differences. The spatstat implementation is usually to be preferred.

References

Baddeley, A., Rubak, E., and Turner, R. 2015. Spatial Point Patterns: Methodology and Applications with R. Chapman and Hall/CRC Press, London. ISBN 9781482210200, https://www.routledge.com/Spatial-Point-Patterns-Methodology-and-Applications-with-R/Baddeley-Rubak-Turner/p/book/9781482210200/.

Fewster, R. M. and Buckland, S. T. 2004. Assessment of distance sampling estimators. In: S. T. Buckland, D. R. Anderson, K. P. Burnham, J. L. Laake, D. L. Borchers and L. Thomas (eds) Advanced distance sampling. Oxford University Press, Oxford, U. K. Pp. 281–306.

Schlather, M., Malinowski, A., Menck, P. J., Oesting, M. and Strokorb, K. 2015. Analysis, simulation and prediction of multivariate random fields with package RandomFields. Journal of Statistical Software, 63, 1–25. URL https://www.jstatsoft.org/v63/i08/.

See Also

popn, plot.popn, randomHabitat, turnover, simulate

Examples


temppop <- sim.popn (D = 10, expand.grid(x = c(0,100), y =
    c(0,100)), buffer = 50)

## plot, distinguishing "M" and "F"
plot(temppop, pch = 1, cex= 1.5,
    col = c("green","red")[covariates(temppop)$sex])

## add a continuous covariate
## assumes covariates(temppop) is non-null
covariates(temppop)$size <- rnorm (nrow(temppop), mean = 15, sd = 3)
summary(covariates(temppop))

## Neyman-Scott cluster distribution (see also rThomas)
par(xpd = TRUE, mfrow=c(2,3))
for (h in c(5,15))
for (m in c(1,4,16)) {
    temppop <- sim.popn (D = 10, expand.grid(x = c(0,100),
        y = c(0,100)), model2D = "cluster", buffer = 100,
        details = list(mu = m, hsigma = h))
    plot(temppop)
    text (50,230,paste(" mu =",m, "hsigma =",h))
}
par(xpd = FALSE, mfrow=c(1,1))   ## defaults

## Inhomogeneous Poisson distribution
xy <- secrdemo.0$mask$x + secrdemo.0$mask$y - 900
tempD <- xy^2 / 1000
plot(sim.popn(tempD, secrdemo.0$mask, model2D = "IHP"))

## Coastal distribution in 1000-m square, homogeneous in
## x-direction
arena <- data.frame(x = c(0, 1000, 1000, 0),
    y = c(0, 0, 1000, 1000))
plot(sim.popn(D = 5, core = arena, buffer = 0, model2D =
    "coastal", details = list(Beta = c(1, 1, 5, 1))))

## Hills
plot(sim.popn(D = 100, core = arena, model2D = "hills",
    buffer = 0, details = list(hills = c(-2,3,0,0))), 
    cex = 0.4)

## tile demonstration
pop <- sim.popn(D = 100, core = make.grid(), model2D = "coastal")
par(mfrow = c(1,2), mar = c(2,2,2,2))
plot(tile(pop, "copy"))
polygon(cbind(-100,200,200,-100), c(-100,-100,200,200),
    col = "red", density = 0)
title("copy")
plot(tile(pop, "reflect"))
polygon(cbind(-100,200,200,-100), c(-100,-100,200,200),
    col = "red", density = 0)
title("reflect")

## Not run: 

## simulate from inhomogeneous fitted density model

regionmask <- make.mask(traps(possumCH), type = "polygon",
    spacing = 20, poly = possumremovalarea)
dts <- distancetotrap(regionmask, possumarea)
covariates(regionmask) <- data.frame(d.to.shore = dts)
dsurf <- predictDsurface(possum.model.Ds, regionmask)
possD <- covariates(dsurf)$D.0
posspop <- sim.popn(D = possD, core = dsurf, model = "IHP")
plot(regionmask, dots = FALSE, ppoly = FALSE)
plot(posspop, add = TRUE, frame = FALSE)
plot(traps(possumCH), add = TRUE)

## randomHabitat demonstration
## - assumes igraph has been installed

# The wrapper function randomDensity may be passed to generate
# a new habitat map each time sim.popn is called. The `details' argument
# of sim.popn is passed to randomDensity as the `parm' argument.

tempmask <- make.mask(nx = 100, ny = 100, spacing = 20)
pop <- sim.popn(D = randomDensity, core = tempmask, model2D = "IHP",
    details = list(D = 10, p = 0.4, A = 0.5))
plot(attr(pop, 'mask'), cov = 'D', dots = FALSE)
plot(pop, add = TRUE)

## rLGCP demonstration
## - assumes spatstat and RandomFields have been installed

if (requireNamespace("spatstat") && requireNamespace("RandomFields")) {
    msk <- make.mask(traps(captdata))
    # details argument 'spacing' ensures core matches Lambda below
    pop <- sim.popn(D = 20, core = msk, buffer = 0, 
        model2D = "rLGCP", details = list(var=1, scale = 30, 
        spacing = spacing(msk)), seed = 1234)
    plot(pop)
    plot(traps(captdata), add = TRUE)

    # another IHP realisation from same LGCP intensity surface
    lgcp <- attr(pop, 'Lambda')
    pop2 <- sim.popn(D = 'Lambda', core = lgcp, model2D = "IHP")
    plot (lgcp, covariate = "Lambda", dots = FALSE)
    plot (pop2, add = TRUE, frame = FALSE)
    
    # check input and output masks match
    summary(lgcp)
    summary(msk)
}


## End(Not run)


secr documentation built on Oct. 18, 2023, 1:07 a.m.