This function implements the acoustic-container (AC) algorithm. To implement the function, a dataframe (or list) of passive acoustic telemetry detections is required (acoustics
). At each time step, the algorithm integrates information from past and future acoustic detections in the form of acoustic containers to determine the possible locations of an individual in an area (see Details).
Under the default options, the approach is implemented step-wise (i.e., step-by-step across the whole time series). The result is a named list of outputs, including a record of the results for each time step, as well as a cumulative map of the expected proportion of time spent in each part of the study area across the whole time series. Alternatively, the approach can be implemented chunk-wise, in which case the acoustic time series is split into chunks (e.g., hourly, daily, monthly segments) and the algorithm is implemented within each chunk step-by-step. The main benefits of this approach are that it can be used to reconstruct putative patterns in space use over biologically meaningful periods separately and/or the chunk-wise implementation can be parallelised, improving computation time. (Chunk-wise results results are easily combined across the duration of the original time series without the loss of information via acdc_simplify
.). This option is implemented if (a) a list, rather than a dataframe, of acoustic detections is provided (via acoustics
); (b) the user specifies that the time series should be split into chunks of a particular duration before the algorithm is initiated (via the split
argument); and/or (c) the algorithm is implemented in parallel via cl
, in which case the acoustic time series is split (if necessary) into user-defined or automatically defined chunks prior to computation. In this case, the result is a named list of outputs, as described above, but in which the results for each chunk are returned separately. If the chunks have been implemented simply to improve computation time via parallelisation, then the maps of space use for each chunk can be combined easily to generate a single, overall map of space use via acdc_simplify
.
ac(
acoustics,
step,
bathy,
plot_ts = TRUE,
detection_containers,
detection_kernels = NULL,
detection_kernels_overlap = NULL,
detection_time_window = 5,
mobility,
normalise = TRUE,
save_record_spatial = 1L,
write_record_spatial_for_pf = NULL,
save_args = TRUE,
verbose = TRUE,
con = "",
progress = 1L,
split = NULL,
cl = NULL,
varlist = NULL
)
A dataframe, or a list of dataframes, that contains passive acoustic telemetry detection time series (see dat_acoustics
for an example) for a single individual. Each dataframe should contain the following columns: an integer vector of receiver IDs, named `receiver_id'; an integer vector of detection indices, named `index'; and a POSIXct vector of time stamps when detections were made, named `timestamp'. If a list of dataframes is supplied, dataframes must be refer to the detections of a single individual and be ordered by time (e.g., in hourly chunks). In addition, sequential list elements must be linked by identical receiver pairs (i.e., the final receiver at which the individual was detected for any given chunk must be the same as the receiver at which the individual was next detected at the start of the next chunk) because it is only in this specific scenario that information does not need to be shared across time steps (see split
). The algorithm will be implemented on each dataframe, termed `chunk', either in sequence or parallel. Any empty or NULL
elements will be removed automatically.
A number that defines the time step length (s). The time series is rounded to the nearest step
to ensure alignment (see Details). `Duplicate' detections (of the same individual at the same receiver in the same step) are dropped.
A raster
that defines a grid across the area within which the individual could have moved. The coordinate reference system should be the Universal Transverse Mercator system, with distances in metres (see also acs_setup_containers
).
A logical input that defines whether or not to the plot detection time series before the algorithm is initiated.
A list of detection containers, with one element for each number from 1:max(acoustics$receiver_id)
, from acs_setup_containers
.
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
).
(optional) A named list, 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.
(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).
A number that defines the (Euclidean) distance (m) that an individual could move in the time steps between sequential detections (see also acs_setup_containers
).
A logical variable that defines whether or not to normalise the map of possible locations at each time step. (The cumulative surface can be normalised via acdc_simplify
).
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 = 0L
suppresses the return of this information and save_record_spatial = NULL
returns this information for all time steps. If the algorithm is applied chunk-wise, this spatial information must be returned for at least the first time step (the default) to aggregate maps across chunks (see acdc_simplify
). This information can also be used to plot time-specific results of the algorithm using acdc_plot_trace
, acdc_plot_record
and acdc_animate_record
.
(optional) A named list, passed to writeRaster
, to save the raster
of the individual's possible positions at each time step to file. The `filename' argument should be the directory in which to save files. Files are named by acoustic and intermediate (archival) time steps. For example, the file for the first acoustic time step and the first archival time step is named acc_1_arc_1.
A logical input that defines whether or not to save the list of function inputs in the returned object.
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 (which is only supported if the algorithm is not implemented in parallel: see below); otherwise, they are written to file (see below).
If verbose = TRUE
, con
is character string that defines how messages relaying function progress are returned. If con = ""
, messages are printed to the console (unless redirected by sink
), an approach that is only implemented if the function is not implemented in parallel. Otherwise, con
defines the directory into which to write .txt files, into which messages are written to relay function progress. This approach, rather than printing to the console, is recommended for clarity, speed and debugging. If the algorithm is implemented step-wise, then a single file is written to the specified directory named acdc_log.txt. If the algorithm is implemented chunk-wise, then an additional file is written for each chunk (named dot_acdc_log_1.txt, dot_acdc_log_2.txt and so on), with the details for each chunk.
(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.
A character string that defines the (approximate) time unit used to split acoustic time series into chunks (e.g., "12 hours"
). If provided, this must be supported by cut.POSIXt
(otherwise, a pre-defined list of acoustic time series can be passed to acoustics
, e.g., specifying seasonal chunks). If split = NULL
and a cluster has been specified (see cl
) (and acoustics
is a dataframe), then the acoustic time series is automatically split into chunks and the algorithm implemented for each chunk in parallel. In all cases, splitting is subject to the constraint that chunks must join at identical receiver pairs (i.e., the last receiver at which the individual was detected on one chunk must match the first receiver at which the individual was next detected at the start of the next chunk): in these specific scenarios, information does not need to transfer from one time step to the next.
(optional) Parallelisation options. cl
is (a) a cluster object from makeCluster
or (b) an integer that defines the number of child processes to implement the algorithm in parallel. If supplied, the algorithm is implemented for each chunk in a list of acoustic time series, either (a) as supplied by the user (if acoustics
is a list), (b) as defined by the input to split
, or (c) as defined automatically from the number of nodes in the cluster if split = NULL
. If cl
is supplied, varlist
may also be required. This is a character vector of objects to export (see cl_export
). Exported variables must be located in the global environment. If a cluster is supplied, the connection to the cluster is closed within the function (see cl_stop
). For further information, see cl_lapply
and flapper-tips-parallel
.
The function returns an acdc_archive-class
object. If a connection to write files has also been specified, an overall log (acdc_log.txt) as well as chunk-specific logs from calls to .acs
, if applicable, are written to file.
The acoustic-container (AC) algorithm is an approach which uses acoustic detections to infer the possible locations of tagged animals within an area over some time interval. The locational information provided by acoustic detections is represented by acoustic containers, which are areas around receivers that define where an individual could have been at each time point given the spatiotemporal pattern of detections at receivers, a model of detection probability and a movement parameter.
In outline, the crux of the approach is the recognition that acoustic detections typically occur irregularly, but we can consider a sequence of regular time steps between any pair of detections. Each detection anchors our knowledge of the location of an individual around a particular receiver (assuming that all detections are true detections). As time passes between pairs of detections, our uncertainty in the geographical location of an individual expands around the receiver at which the individual was detected before shrinking towards the receiver at which it was next detected. The dynamics of this process are captured by the expansion, contraction and intersection of pairs of acoustic containers.
More specifically, at each time step, we can consider the set of possible locations for the individual from perspective of (a) the receiver at which the individual was detected and (b) the receiver at which the individual is next detected. When an individual is detected, it must be within some radius---say 800 m---of that receiver termed the `detection container'. From the perspective of the receiver at which the individual is next detected, the set of possible locations of the individual is wider in line with the time between detections and the movement speed of the animal. The intersection of these two areas defines the set of possible locations for the individual. (In most cases, this is simply that defined by the detection container around the first receiver.) With a more-refined model of detection probability, it may be possible to predict more precisely where the individual is likely to have been within this area. (In situations with depth data, the ACDC algorithm further restricts the set of locations by incorporating information on the animal's depth via depth contours.) Moving forward in time, we can consider a number of regular time steps before the next detection. During this time, from the perspective of the receiver at which the individual was detected, the set of possible locations of the individual expands, because it could have moved further away from the receiver; meanwhile, from the perspective of the receiver at which the individual was next detected, the set of possible locations of the individual shrinks, as the individual must have been located within the detection container of that receiver by the time of the detection. This process is described by the expansion and contraction of `acoustic containers'. At each time step, the intersection of the two containers defines the set of possible locations of the individual, possibly weighted by a detection probability (given the lack of detections during this time). These dynamics recognise that as time passes between detections the individual could have moved away from the receiver at which it was last detected but only at a rate and in a direction that fits with the receiver at which the individual was next detected. Thus, when the individual is detected again, our uncertainty about where it could have been collapses to the detection container around the next receiver (and its intersection with the individual's previous (expanded) location and the acoustic container around the following receiver), possibly weighted by a model of detection probability. Throughout this process, the rate of change in container size depends a movement parameter that describes the maximum swimming speed.
This discussion assumes that the timing of detections and intermediate time steps between detections are perfectly aligned. In reality, there is likely to be a mismatch between the timing of detections and the intermediate time steps between detections, which may be poorly approximated the constant expansion and contraction of acoustic containers. The simplest solution to this issue is to round the acoustic time steps to the resolution of the intermediate time steps (specified by step
). This results in a small loss of precision, but assuming that step
is relatively small, the effect should be negligible. In any case, clocks on different receivers are unlikely to be perfectly synced throughout a study. This solution is also computationally preferable to an alternative approach in which the expansion and contraction of containers varies through time, depending on the gaps between observations and other time-specific variables such as behavioural state. However, the latter approach may be implemented in due course.
The end result is a map that shows the expected time spent in different parts of a study area. The main limitation of this approach is the simple treatment of movement, but particle filtering can be used to extent this approach via the incorporate a movement model (see pf
).
This function calls .acs_pl
and .acs
to implement the AC algorithm. 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. acdc_simplify
simplifies the outputs and acdc_plot_trace
, acdc_plot_record
and acdc_animate_record
visualise the results. The AC algorithm can be extended to incorporate depth contours via acdc
. Particle filtering can be used to reconstruct movement path via pf
.
#### Step (1) Implement setup_acdc_*() steps
# ... Define detection containers required for AC algorithm (see setup_acdc_containers())
#### Step (2) Prepare movement time series for algorithm
# Focus on an example individual for speed
id <- 25
acc <- dat_acoustics[dat_acoustics$individual_id == id, ][1:25, ]
# Process time series (if necessary)
# ... Observations should be processed to the nearest time step
# ... Duplicate detections should be dropped
#### Example (1) Implement AC algorithm with default arguments
# This implements the algorithm on a single core, printing messages
# ... to the console to monitor function progress.
out_ac <- ac(
acoustics = acc,
step = 120,
bathy = dat_gebco,
detection_containers = dat_containers,
mobility = 200
)
#> flapper::ac() called (@ 2023-08-29 15:20:42)...
#> flapper::.acs_pl() called (@ 2023-08-29 15:20:42)...
#> ... Checking user inputs...
#> The legacy packages maptools, rgdal, and rgeos, underpinning the sp package,
#> which was just loaded, will retire in October 2023.
#> Please refer to R-spatial evolution reports for details, especially
#> https://r-spatial.org/r/2023/05/15/evolution4.html.
#> It may be desirable to make the sf package available;
#> package maintainers should consider adding sf to Suggests:.
#> The sp package is now running under evolution status 2
#> (status 2 uses the sf package in place of rgdal)
#> ... Processing movement time series...
#> ... Plotting movement time series (for each chunk)...
#> ... Calling .acs() to implement ACDC algorithm on one chunk...
#> flapper::.acs() called (@ 2023-08-29 15:20:46)...
#>
|
| | 0%... Initiating algorithm: moving over acoustic and internal ('archival') time steps...
#> ... On acoustic time step ('timestep_detection') 1.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|=== | 4%... On acoustic time step ('timestep_detection') 2.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|====== | 8%... On acoustic time step ('timestep_detection') 3.
#> ... ... On internal time step ('timestep_archival') 1.
#> ... ... On internal time step ('timestep_archival') 2.
#> ... ... ... Acoustic container is expanding...
#> rgeos version: 0.6-4, (SVN revision 699)
#> GEOS runtime version: 3.11.0-CAPI-1.17.0
#> Please note that rgeos will be retired during October 2023,
#> plan transition to sf or terra functions using GEOS at your earliest convenience.
#> See https://r-spatial.org/r/2023/05/15/evolution4.html for details.
#> GEOS using OverlayNG
#> Linking to sp version: 2.0-0
#> Polygon checking: TRUE
#> Warning: GEOS support is provided by the sf and terra packages among others
#>
|
|========= | 12%... On acoustic time step ('timestep_detection') 4.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|============ | 17%... On acoustic time step ('timestep_detection') 5.
#> ... ... On internal time step ('timestep_archival') 1.
#> ... ... On internal time step ('timestep_archival') 2.
#> ... ... ... Acoustic container is expanding...
#> Warning: GEOS support is provided by the sf and terra packages among others
#>
|
|=============== | 21%... On acoustic time step ('timestep_detection') 6.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|================== | 25%... On acoustic time step ('timestep_detection') 7.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|==================== | 29%... On acoustic time step ('timestep_detection') 8.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|======================= | 33%... On acoustic time step ('timestep_detection') 9.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|========================== | 38%... On acoustic time step ('timestep_detection') 10.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|============================= | 42%... On acoustic time step ('timestep_detection') 11.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|================================ | 46%... On acoustic time step ('timestep_detection') 12.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|=================================== | 50%... On acoustic time step ('timestep_detection') 13.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|====================================== | 54%... On acoustic time step ('timestep_detection') 14.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|========================================= | 58%... On acoustic time step ('timestep_detection') 15.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|============================================ | 62%... On acoustic time step ('timestep_detection') 16.
#> ... ... On internal time step ('timestep_archival') 1.
#> ... ... On internal time step ('timestep_archival') 2.
#> ... ... ... Acoustic container is expanding...
#> Warning: GEOS support is provided by the sf and terra packages among others
#> ... ... On internal time step ('timestep_archival') 3.
#> ... ... ... Acoustic container is constant ...
#>
|
|=============================================== | 67%... On acoustic time step ('timestep_detection') 17.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|================================================== | 71%... On acoustic time step ('timestep_detection') 18.
#> ... ... On internal time step ('timestep_archival') 1.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> ... ... On internal time step ('timestep_archival') 2.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> ... ... On internal time step ('timestep_archival') 3.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> ... ... On internal time step ('timestep_archival') 4.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> ... ... On internal time step ('timestep_archival') 5.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> ... ... On internal time step ('timestep_archival') 6.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> ... ... On internal time step ('timestep_archival') 7.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> ... ... On internal time step ('timestep_archival') 8.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> ... ... On internal time step ('timestep_archival') 9.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> ... ... On internal time step ('timestep_archival') 10.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#>
|
|==================================================== | 75%... On acoustic time step ('timestep_detection') 19.
#> ... ... On internal time step ('timestep_archival') 1.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#>
|
|======================================================= | 79%... On acoustic time step ('timestep_detection') 20.
#> ... ... On internal time step ('timestep_archival') 1.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#>
|
|========================================================== | 83%... On acoustic time step ('timestep_detection') 21.
#> ... ... On internal time step ('timestep_archival') 1.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#>
|
|============================================================= | 88%... On acoustic time step ('timestep_detection') 22.
#> ... ... On internal time step ('timestep_archival') 1.
#> Warning: GEOS support is provided by the sf and terra packages among others
#> Warning: GEOS support is provided by the sf and terra packages among others
#>
|
|================================================================ | 92%... On acoustic time step ('timestep_detection') 23.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|=================================================================== | 96%... On acoustic time step ('timestep_detection') 24.
#> ... ... On internal time step ('timestep_archival') 1.
#>
|
|======================================================================| 100%
#> ... Movement over acoustic and internal ('archival') time steps has been completed.
#> ... flapper::.acs() call completed (@ 2023-08-29 15:20:49) after ~0.05 minutes.
#> ... flapper::.acs_pl() call completed (@ 2023-08-29 15:20:50) after ~0.12 minutes.
#> flapper::ac() finished (@ 2023-08-29 15:20:50)...
#### Subsequent examples follow the implementation given in acdc().