dot-acs: Back-end implementation of the AC and ACDC algorithms

.acsR Documentation

Back-end implementation of the AC and ACDC algorithms

Description

This function is the back-end of the acoustic-container (AC) and acoustic-container depth-contour (ACDC) algorithms.

Usage

.acs(
  acoustics,
  archival = NULL,
  step = 120,
  round_ts = TRUE,
  plot_ts = TRUE,
  bathy,
  map = NULL,
  detection_containers,
  detection_kernels = NULL,
  detection_kernels_overlap = NULL,
  detection_time_window = 5,
  mobility,
  calc_depth_error = function(...) matrix(c(-2.5, 2.5), nrow = 2),
  normalise = TRUE,
  chunk = 1L,
  save_record_spatial = 1L,
  write_record_spatial_for_pf = NULL,
  save_args = TRUE,
  verbose = TRUE,
  con = "",
  progress = 1L,
  check = TRUE
)

Arguments

acoustics

A dataframe that contains passive acoustic telemetry detection time series for a specific individual (see dat_acoustics for an example). This should contain the following columns: an integer vector of receiver IDs, named ‘receiver_id’ (that must match that inputted to acs_setup_containers); an integer vector of detection indices, named ‘index’; a POSIXct vector of time stamps when detections were made, named ‘timestamp’; and a numeric vector of those time stamps, named ‘timestamp_num’.

archival

For the ACDC algorithm, archival is a dataframe that contains depth time series for the same individual (see dat_archival for an example). This should contain the following columns: a numeric vector of observed depths, named ‘depth’; a POSIXct vector of time stamps when observations were made, named ‘timestamp’; and a numeric vector of those time stamps, named ‘timestamp_num’. Depths should be recorded in the same units and with the same sign as the bathymetry data (see bathy). Absolute depths (m) are suggested. Unlike the detection time series, archival time stamps are assumed to have occurred at regular intervals.

step

A number that defines the time step length (s) between consecutive detections. If archival is supplied, this is the resolution of the archival data (e.g., 120 s).

round_ts

A logical input that defines whether or not to round the acoustics and/or archival time series to the nearest step/60 minutes. This step is necessary to ensure appropriate alignment between the two time series given the assumption of a constant mobility parameter (see below). For implementations via .acs_pl, this step is implemented in .acs_pl.

plot_ts

A logical input that defines whether or not to the plot movement series before the algorithm is initiated.

bathy

A raster that defines the area (for the AC algorithm) or bathymetry (for the ACDC* algorithm) across the area within which the individual could have moved. For the ACDC algorithm, this must be recorded in the same units and with the same sign as the depth observations (see archival). The coordinate reference system should be the Universal Transverse Mercator system, with distances in metres (see also acs_setup_containers).

map

(optional) A blank raster, with the same properties (i.e., dimensions, resolution, extent and coordinate reference system) as the area/bathymetry raster (see bathy), but in which all values are 0. If NULL, this is computed internally, but supplying a pre-defined raster can be more computationally efficient if the function is applied iteratively (e.g., over different time windows).

detection_containers

A list of detection containers, with one element for each number from 1:max(acoustics$receiver_id), from acs_setup_containers.

detection_kernels

A named list of detection probability kernels, from acs_setup_detection_kernels and created using consistent parameters as specified for other acs_setup_* functions and here (i.e., see the overlaps, calc_detection_pr and map arguments in acs_setup_detection_kernels).

detection_kernels_overlap

(optional) A named list (the ‘list_by_receiver’ element from get_detection_containers_overlap), that defines, for each receiver, for each day over its deployment period, whether or not its detection container overlapped with those of other receivers. If detection_kernels_overlap and detection_time_window (below) are supplied, the implementation of detection probability kernels when a detection is made accounts for overlaps in receivers' detection containers; if unsupplied, receiver detection probability kernels are assumed not to overlap.

detection_time_window

(optional) A number that defines the maximum duration (s) between consecutive detections at different receivers such that they can be said to have occurred at ‘effectively the same time’. This indicates that the same transmission was detected by multiple receivers. If detection_kernels_overlap (above) and detection_time_window are supplied, the implementation of detection probability kernels when a detection is made accounts for overlaps in receivers' detection containers, by up-weighting overlapping areas between receivers that detected the transmission and down-weighting overlapping areas between receivers that did not detect the transmission (see Details in acs_setup_detection_kernels). Note that the timing of detections is affected by step (see Details).

mobility

A number that defines the distance (m) that an individual could move in the time steps between acoustic detections (see also acs_setup_containers).

calc_depth_error

In the ACDC algorithm, calc_depth_error is function that returns the depth errors around a vector of depths. The function should accept vector of depths (from archival$depth) and return a matrix, with one row for each (lower and upper) error and one one column for each depth (if the error varies with depth). For each depth, the two numbers are added to the observed depth to define the range of depths on the bathymetry raster (bathy) that the individual could plausibly have occupied at any time. Since the depth errors are added to the individual's depth, the first number should be negative (i.e., the individual could have been shallower that observed) and the second positive (i.e., the individual could have been deeper than observed). The appropriate form for calc_depth_error depends on the species (pelagic versus demersal/benthic species), the measurement error for the depth observations in archival and bathymetry (bathy) data, as well as the tidal range (m) across the area (over the duration of observations). For example, for a pelagic species, the constant function calc_depth_error = function(...) matrix(c(-2.5, Inf) implies that the individual could have occupied bathymetric cells that are deeper than the observed depth + (-2.5) m and shallower than Inf m (i.e. the individual could have been in any location in which the depth was deeper than the shallow depth limit for the individual). In contrast, for a benthic species, the constant function calc_depth_error = function(...) matrix(c(-2.5, 2.5), nrow = 2) implies that the individual could have occupied bathymetric cells whose depth lies within the interval defined by the observed depth + (-2.5) and + (+2.5) m.

normalise

A logical variable that defines whether or not to normalise the map of possible locations at each time step so that they sum to one.

chunk

An integer that defines the chunk ID (from .acs_pl).

save_record_spatial

An integer vector that defines the time steps for which to save a record of the spatial information from each time step. save_record_spatial = 0 suppresses the return of this information and save_record_spatial = NULL returns this information for all time steps.

write_record_spatial_for_pf

(optional) A named list, passed to writeRaster, to save a subset of the spatial record (specifically the raster of the individual's possible positions at each time step) to file. This forms the basis for extending maps of space use via particle filtering (see pf.) The ‘filename’ argument should be the directory in which to save files. Files are named by chunk ID, acoustic and internal (archival) time steps. For example, the file for the first chunk, the first acoustic time step and the first archival time step is named ‘chu_1_acc_1_arc_1’.

save_args

A logical input that defines whether or not to include a list of function arguments in the outputs. This can be switched off if the function is applied iteratively.

verbose

A logical variable that defines whether or not to print messages to the console or to file to relay function progress. If con = "", messages are printed to the console; otherwise, they are written to file (see below).

con

If verbose = TRUE, con is character string that defines the full pathway to a .txt file (which can be created on-the-fly) into which messages are written to relay function progress. This approach, rather than printing to the console, is recommended for clarity, speed and debugging.

progress

(optional) If the algorithm is implemented step-wise, progress is an integer (1, 2 or 3) that defines whether or not to display a progress bar in the console as the algorithm moves over acoustic time steps (1), the ‘archival’ time steps between each pair of acoustic detections (2) or both acoustic and archival time steps (3), in which case the overall acoustic progress bar is punctuated by an archival progress bar for each pair of acoustic detections. This option is useful if there is a large number of archival observations between acoustic detections. Any other input will suppress the progress bar. If the algorithm is implemented for chunks, inputs to progress are ignored and a single progress bar is shown of the progress across acoustic chunks.

check

A logical input that defines whether or not to check function inputs. This can be switched off to improve computation time when the function is applied iteratively or via a front-end function (e.g., ac or acdc).

Value

The function returns an acdc_record-class object with the following elements: ‘map’, ‘record’, ‘time’, ‘args’, ‘chunks’ and ‘simplify’. The main output element is the ‘map’ RasterLayer that shows where the individual could have spent more or less time over the duration of the movement time series. The ‘record’ element records time-specific information on the possible locations of the individual, and can be used to plot maps of specific time points or to produce animations (for the time steps specified by save_record_spatial). The ‘time’ element is a dataframe that defines the times of sequential stages in the algorithm's progression, providing a record of computation time. The ‘args’ element is a named list of user inputs that record the parameters used to generate the outputs (if save_args = TRUE, otherwise the ‘args’ element is NULL).

Author(s)

Edward Lavender

See Also

The front-end functions ac and acdc call .acs_pl which in turn calls this function. acs_setup_containers defines the detection containers required by this function. acs_setup_mobility is used to examine the assumption of the constant ‘mobility’ parameter. acs_setup_detection_kernels produces detection probability kernels for incorporation into the function. For calls via ac and acdc, acdc_simplify simplifies the outputs and acdc_plot_trace, acdc_plot_record and acdc_animate_record visualise the results.

Examples

#### Step (1) Prepare study site grid
# Grid resolution needs to be sufficiently high to capture detection probability/movement
# And sufficiently low to minimise computational costs
blank <- raster::raster(raster::extent(dat_gebco), res = c(75, 75))
gebco <- raster::resample(dat_gebco, blank)

#### Step (2) Implement setup_acdc_*() steps
# ... Define detection containers required for algorithm(s) (see acs_setup_containers())

#### Step (3) Prepare movement time series for algorithm(s)
# Add required columns to dataframes:
dat_acoustics$timestamp_num <- as.numeric(dat_acoustics$timestamp)
dat_archival$timestamp_num <- as.numeric(dat_archival$timestamp)
# Focus on an example individual
id <- 25
acc <- dat_acoustics[dat_acoustics$individual_id == id, ]
arc <- dat_archival[dat_archival$individual_id == id, ]
# Focus on the subset of data for which we have both acoustic and archival detections
acc <- acc[acc$timestamp >= min(arc$timestamp) - 2 * 60 &
  acc$timestamp <= max(arc$timestamp) + 2 * 60, ]
arc <- arc[arc$timestamp >= min(acc$timestamp) - 2 * 60 &
  arc$timestamp <= max(acc$timestamp) + 2 * 60, ]
# We'll focus on a one day period with overlapping detection/depth time series for speed
end <- as.POSIXct("2016-03-18")
acc <- acc[acc$timestamp <= end, ]
arc <- arc[arc$timestamp <= end, ]
arc <- arc[arc$timestamp >= min(acc$timestamp) - 2 * 60 &
  arc$timestamp <= max(acc$timestamp) + 2 * 60, ]
# Process time series
# ... Detections should be rounded to the nearest step
# ... Duplicate detections
# ... ... (of the same individual at the same receiver in the same step)
# ... ... should be dropped
# ... This step has already been implemented for dat_acoustics.

#### Example (1) Implement AC algorithm with default arguments
out_acdc_1 <- flapper:::.acs(
  acoustics = acc,
  bathy = gebco,
  detection_containers = dat_containers,
  mobility = 200
)

#### Example (2) Implement ACDC algorithm with default arguments
out_acdc_2 <- flapper:::.acs(
  acoustics = acc,
  archival = arc,
  bathy = gebco,
  detection_containers = dat_containers,
  mobility = 200,
  calc_depth_error = function(...) matrix(c(-2.5, 2.5), nrow = 2)
)

#### Example (3) Implement AC or ACDC algorithm with detection probability kernels

## (A) Get detection container overlaps
# Define receiver locations as a SpatialPointsDataFrame object with a UTM CRS
proj_wgs84 <- sp::CRS(SRS_string = "EPSG:4326")
proj_utm <- sp::CRS(SRS_string = "EPSG:32629")
rownames(dat_moorings) <- dat_moorings$receiver_id
xy <- sp::SpatialPoints(
  dat_moorings[, c("receiver_long", "receiver_lat")],
  proj_wgs84
)
xy <- sp::spTransform(xy, proj_utm)
xy <- sp::SpatialPointsDataFrame(xy, dat_moorings[, c(
  "receiver_id",
  "receiver_start_date",
  "receiver_end_date"
)])
# Get detection overlap(s) as a SpatialPolygonsDataFrame
containers <- get_detection_containers(
  xy = sp::SpatialPoints(xy),
  detection_range = 425,
  coastline = dat_coast,
  byid = TRUE
)
containers_df <- dat_moorings[, c(
  "receiver_id",
  "receiver_start_date",
  "receiver_end_date"
)]
row.names(containers_df) <- names(containers)
containers <- sp::SpatialPolygonsDataFrame(containers, containers_df)
overlaps <- get_detection_containers_overlap(containers = containers)

## (B) Define detection probability function based on distance and detection_range
calc_dpr <-
  function(x) {
    ifelse(x <= 425, stats::plogis(2.5 + -0.02 * x), 0)
  }

## (C) Get detection kernels (a slow step)
kernels <- acs_setup_detection_kernels(
  xy = xy,
  containers = dat_containers,
  overlaps = overlaps,
  calc_detection_pr = calc_dpr,
  bathy = gebco
)
## (D) Implement algorithm
out_acdc_3 <- flapper:::.acs(
  acoustics = acc,
  archival = arc,
  bathy = gebco,
  detection_containers = dat_containers,
  detection_kernels = kernels,
  detection_kernels_overlap = overlaps$list_by_receiver,
  detection_time_window = 10,
  mobility = 200,
  calc_depth_error = function(...) matrix(c(-2.5, 2.5), nrow = 2)
)

#### Example (4): Compare outputs with/without detection probability and normalisation
## Without detection kernels
out_acdc_4a <- flapper:::.acs(
  acoustics = acc,
  archival = arc,
  bathy = gebco,
  detection_containers = dat_containers,
  mobility = 200,
  calc_depth_error = function(...) matrix(c(-2.5, 2.5), nrow = 2)
)
out_acdc_4b <- flapper:::.acs(
  acoustics = acc,
  archival = arc,
  bathy = gebco,
  detection_containers = dat_containers,
  normalise = TRUE,
  mobility = 200,
  calc_depth_error = function(...) matrix(c(-2.5, 2.5), nrow = 2)
)
## With detection kernels
out_acdc_4c <- flapper:::.acs(
  acoustics = acc,
  archival = arc,
  bathy = gebco,
  detection_containers = dat_containers,
  detection_kernels = kernels,
  mobility = 200,
  calc_depth_error = function(...) matrix(c(-2.5, 2.5), nrow = 2)
)
out_acdc_4d <- flapper:::.acs(
  acoustics = acc,
  archival = arc,
  bathy = gebco,
  detection_containers = dat_containers,
  detection_kernels = kernels, normalise = TRUE,
  mobility = 200,
  calc_depth_error = function(...) matrix(c(-2.5, 2.5), nrow = 2)
)
## Comparison of final maps
pp <- par(mfrow = c(2, 2))
raster::plot(out_acdc_4a$map, main = "4a")
raster::plot(out_acdc_4b$map, main = "4b")
raster::plot(out_acdc_4c$map, main = "4c")
raster::plot(out_acdc_4d$map, main = "4d")
par(pp)

#### Example (5): Implement AC or ACDC algorithm and write messages to file via 'con'
out_acdc_5 <- flapper:::.acs(
  acoustics = acc,
  archival = arc,
  bathy = gebco,
  detection_containers = dat_containers,
  mobility = 200,
  calc_depth_error = function(...) matrix(c(-2.5, 2.5), nrow = 2),
  verbose = TRUE,
  con = paste0(tempdir(), "/", "acdc_log.txt")
)
# Check log
utils::head(readLines(paste0(tempdir(), "/", "acdc_log.txt")))
utils::tail(readLines(paste0(tempdir(), "/", "acdc_log.txt")))

#### Example (6): Implement AC or ACDC algorithm and return spatial information
# Specify save_record_spatial = NULL to include spatial information for all time steps
# ... (used for plotting) or a vector to include this information for specific time steps
out_acdc_6 <- flapper:::.acs(
  acoustics = acc,
  archival = arc,
  bathy = gebco,
  detection_containers = dat_containers,
  mobility = 200,
  calc_depth_error = function(...) matrix(c(-2.5, 2.5), nrow = 2),
  save_record_spatial = NULL,
  verbose = TRUE,
  con = paste0(tempdir(), "/", "acdc_log.txt")
)


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