sim_path_sa: Simulate discrete-time movement paths from step lengths and...

View source: R/sims.R

sim_path_saR Documentation

Simulate discrete-time movement paths from step lengths and turning angles

Description

This function simulates movement paths from step lengths and turning angles. To implement the function, the number of time steps (n) needs to be specified and, if applicable, the area within which movement should occur. For example, in marine environments, the inclusion of the sea as a spatial or raster layer would restrict movement within the sea*. The starting location (p_1) can be provided or simulated. At each time step, user-defined functions are used to simulate step lengths and turning angles, which can depend previous values of those variables via a lag parameter, from which the next position is calculated. This implementation enables movement paths to be simulated under a variety of movement models, including random walks and correlated random walks, providing that they are conceptualised in terms of step lengths and turning angles. The function returns a list of outputs that includes the simulated path and, if requested, produces a plot of the simulated path.

Usage

sim_path_sa(
  n = 10,
  area = NULL,
  p_1 = NULL,
  sim_angle = sim_angles,
  sim_step = sim_steps,
  lag = 0L,
  plot = TRUE,
  add_points = list(pch = 21, bg = "darkgreen"),
  add_path = list(length = 0.05, col = viridis::viridis(n)),
  add_area = if (is.null(area)) NULL else list(),
  seed = NULL,
  verbose = TRUE,
  ...
)

sim_steps(...)

sim_angles(...)

Arguments

n

An integer that defines the number of time steps in the simulation.

area

(optional) A SpatialPolygons-class, SpatialPolygonsDataFrame-class or raster object that defines the area(s) within which movement is allowed.

p_1

(optional) A matrix with one row and two columns that defines the starting location (x, y). If p_1 = NULL, then a random location is sampled from area, if applicable, or simulated from a uniform distribution with a minimum and maximum value of 0 and 1 respectively.

sim_angle

A function that is used to simulate turning angles. This must accept a single number that represents some previous turning angle (degrees), even if this is simply ignored (see lag, below). For example, sim_angle = function() 1 will break but sim_angle = function(...) 1 is fine. For convenience, a default function is included that simulates angles from a wrapped normal circular distribution with a mean and standard deviation of 1 (see rwrappednormal). Functions that actually depend on some previous angle also need to be able to generate initial angles before enough previous angles have been generated for the function to depend on those (see lag, below). All functions should return a single number that defines the turning angle in degrees.

sim_step

A function that is used to simulate step lengths. This follows the same rules as for sim_angle. For convenience, a default function is included that simulates angles from a gamma distribution with shape and scale parameters of 15 (see rgamma).

lag

If sim_angle and/or sim_step have been defined such that they depend on some previous angle/step length, then lag is an integer that defines the number of time steps between the current time step and some previous time step that affects the current turning angle and/or step length.

plot

A logical variable that defines whether or not to produce a plot of the area (if provided) and the simulated movement path.

add_area, add_points, add_path

(optional) Named lists of arguments that are used to customise the appearance of the area, points (the starting location) and the path on the map, passed to the add_polys, add_points and add_points arguments of pretty_map.

seed

(optional) An integer that defines the seed (for reproducible simulations: see set.seed).

verbose

A logical variable that defines whether or not to print messages to the console that relay function progress.

...

Additional arguments. For sim_path_sa, these are passed to pretty_map to customise the map. For the default sim_angles and sim_steps functions, ... is required but additional parameters are ignored.

Details

*Strictly speaking, only sequential positions are restricted to be within the allowed area. Yet since steps in the current implementation of the function are linear, the simulation of relatively large step lengths in an area with complex barriers to movement (e.g., convoluted coastlines), may lead to movement over inappropriate areas (e.g., over a peninsula) even through sequential positions are within the allowed area (e.g., either side of a peninsula). This problem can be mitigated by simulating time series for which sequential observations are closer in time (and thus for which step lengths are more constrained). For longer time series for which short time steps are undesirable, least-cost paths (e.g., see lcp_over_surface) may be implemented to ensure biologically meaningful movements in future (but this is more computationally demanding for rapid simulations).

For coupled simulation–analysis workflows (such as sim_array, sim_path_sa and sim_detections plus ac, dc, acdc and pf) note that the representation of the area as SpatialPolygons-class or SpatialPolygonsDataFrame-class objects by the sim_* functions, rather than a raster grid, may be problematic at the land–sea interface if the Spatial* data used for the simulation do not agree precisely with the raster data used to reconstruct movements: locations that are ‘allowed’ from the perspective of the Spatial* data may not be allowed by the raster data (and vice versa). Furthermore, distances in the Spatial* data may differ from distances in the raster data depending on grid resolution. At the time of writing, this can be resolved in two ways. (A) Check simulated movements in relation to the grid across which movements are reconstructed. Animal locations should also be translated onto the raster before simulating detections (see sim_detections). Movement distances should remain admissible under the movement model. (B) For this function, you can now use a raster to simulate receiver locations (see also acs_setup_containers).

This function requires the circular package.

Value

The function returns a named list of arguments that defines the simulated path (‘xy_mat’, ‘angle_mat’, ‘step_mat’ and ‘path’) and a named list of arguments that were used to generate the path (‘args’). ‘xy_mat’ is an n-row, two-column matrix that defines the simulated position (x, y) at each time step; ‘angle_mat’ and ‘step_mat’ are n-row, one-column matrices that define the simulated turning angle (degrees) and step length (in map units) at each time step; and ‘path’ is a SpatialLines representation of the movement path.

Author(s)

Edward Lavender

See Also

For movement simulations, see sim_path_* for the full list of functions currently implemented in flapper. For example, sim_path_ou_1 simulates a movement path based on past locations according to an Ornstein-Uhlenbeck process (which is not based on step lengths and turning angles). More broadly, sim_array, sim_path_* and sim_detections provide an integrated workflow for simulating acoustic arrays, movement paths in these areas and detections at receivers arising from movement.

Examples

#### Example (1): Simulate movement path under default parameters
# Simulate path
path <- sim_path_sa()
# The function returns a list of parameters that define the array and a plot
summary(path)

#### Example (2): Change the number of time steps
path <- sim_path_sa(n = 100)

#### Example (3): Change the characteristics of the study area
# .. and define the starting location of the individual
sea <- invert_poly(dat_coast)
path <- sim_path_sa(
  n = 100,
  area = sea,
  p_1 = matrix(c(706529.1, 6262293), ncol = 2),
  add_area = list(x = sea, col = "skyblue")
)

#### Example (4): Change the movement model(s) to use alternative distributions/parameters

## Step lengths
# Define new function to simulate step lengths
sim_step_lengths <- function(...) stats::rgamma(1, shape = 10, scale = 1)
# Check outputs suitable values
prettyGraphics::pretty_hist(replicate(n = 1000, expr = sim_step_lengths()))
# Implement simulation
path <- sim_path_sa(n = 100, sim_step = sim_step_lengths)
prettyGraphics::pretty_hist(as.numeric(path$step_mat))

## Turning angles
# E.g., Random walk: draw turning angle from von Mises distribution
sim_angles_vmd <- function(...) {
  angle <- circular::rvonmises(
    n = 1,
    mu = circular::circular(0),
    kappa = 0,
    control.circular = list(units = "degrees")
  )
  return(as.numeric(angle))
}
path <- sim_path_sa(n = 100, sim_angle = sim_angles_vmd)

# E.g., Correlated random walk: draw turning angle from wrapped normal distribution
sim_angles_rwn <- function(...) {
  angle <- circular::rwrappednormal(
    n = 1,
    mu = circular::circular(0),
    rho = 0.999,
    sd = 0,
    control.circular = list(units = "degrees")
  )
  return(as.numeric(angle))
}
path <- sim_path_sa(n = 100, sim_angle = sim_angles_rwn)

#### Example (5) Change the movement models to depend on some lagged value
# ... of the variable in question
# Define a sim_angle function that depends on some previous angle
# While the time step is less than the lag, the function needs to be
# ... able to handle missing angles and return sensible values in these
# ... cases e.g., via an 'is.null' structure:
sim_angles_wrn_with_lag <- function(angle = NULL, ...) {
  if (is.null(angle)) {
    cat("\n... ... method (1) activated...\n") # useful check
    angle_out <- circular::circular(0)
  } else {
    angle_out <- circular::rwrappednormal(
      n = 1,
      mu = circular::circular(angle, units = "degrees"),
      rho = 0.9,
      sd = 0.1,
      control.circular = list(units = "degrees")
    )
  }
  return(as.numeric(angle_out))
}
# Check function
sim_angles_wrn_with_lag(NULL)
sim_angles_wrn_with_lag(1)
# Implement algorithm
path <- sim_path_sa(sim_angle = sim_angles_wrn_with_lag, lag = 1)
path <- sim_path_sa(sim_angle = sim_angles_wrn_with_lag, lag = 2)


edwardlavender/flapper documentation built on Jan. 22, 2025, 2:44 p.m.