Skip to content

Commit

Permalink
Update routines for examining 'probability of use' from particle hist…
Browse files Browse the repository at this point in the history
…ories by focussing on the most probable records for connected particles.
  • Loading branch information
edwardlavender committed Aug 26, 2021
1 parent 8e618be commit e38985c
Show file tree
Hide file tree
Showing 11 changed files with 278 additions and 146 deletions.
43 changes: 22 additions & 21 deletions R/pf.R
Original file line number Diff line number Diff line change
Expand Up @@ -493,27 +493,28 @@ pf <- function(record,
#### Define storage container for outputs
if(!is.null(seed)) set.seed(seed)
out_pf <- list(history = NULL,
args = list(record = record,
data = data,
origin = origin,
calc_distance = calc_distance,
calc_distance_euclid_fast = calc_distance_euclid_fast,
bathy = bathy,
calc_distance_graph = calc_distance_graph,
calc_movement_pr = calc_movement_pr,
calc_movement_pr_from_origin = calc_movement_pr_from_origin,
mobility = mobility,
mobility_from_origin = mobility_from_origin,
n = n,
resample = resample,
update_history = update_history,
update_history_from_time_step = update_history_from_time_step,
cl = cl,
use_all_cores = use_all_cores,
seed = seed,
verbose = verbose,
dots = list(...)
)
method = "pf",
args = list(record = record,
data = data,
origin = origin,
calc_distance = calc_distance,
calc_distance_euclid_fast = calc_distance_euclid_fast,
bathy = bathy,
calc_distance_graph = calc_distance_graph,
calc_movement_pr = calc_movement_pr,
calc_movement_pr_from_origin = calc_movement_pr_from_origin,
mobility = mobility,
mobility_from_origin = mobility_from_origin,
n = n,
resample = resample,
update_history = update_history,
update_history_from_time_step = update_history_from_time_step,
cl = cl,
use_all_cores = use_all_cores,
seed = seed,
verbose = verbose,
dots = list(...)
)
)

#### Checks
Expand Down
51 changes: 41 additions & 10 deletions R/pf_analyse_archive.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#' @title Plot particle histories from a PF algorithm
#' @description This function plots the spatiotemporal particle histories from a particle filtering (PF) algorithm (the acoustic-centroid PF, the depth-contour PF or the acoustic-centroid depth-contour PF). This produces, for each time step, a map of the individual's possible locations (from the AC, DC or ACDC algorithm), with sampled locations (derived via the particle filtering routine) overlaid.
#' @param archive A \code{\link[flapper]{pf_archive-class}} object from \code{\link[flapper]{pf}} that contains particle histories.
#' @param archive A \code{\link[flapper]{pf_archive-class}} object from \code{\link[flapper]{pf}}, or \code{\link[flapper]{pf}} plus \code{\link[flapper]{pf_simplify}} with the \code{record = "archive"} argument, that contains particle histories.
#' @param time_steps An integer vector that defines the time steps for which to plot particle histories.
#' @param add_surface A named list, passed to \code{\link[prettyGraphics]{pretty_map}}, to customise the appearance of the surface, which shows the set of possible positions that the individual could have occupied at a given time step (from \code{\link[flapper]{ac}}, \code{\link[flapper]{dc}} and \code{\link[flapper]{acdc}}), on each map.
#' @param add_particles A named list, passed to \code{\link[prettyGraphics]{pretty_map}}, to customise the appearance of the particles on each map.
Expand Down Expand Up @@ -39,6 +39,18 @@
#' pf_plot_history(dat_dcpf_histories, time_steps = 1:4, prompt = FALSE)
#' graphics::par(pp)
#'
#' #### Example (4): Compare outputs for sampled versus connected particles
#' dat_dcpf_histories_connected <-
#' pf_simplify(dat_dcpf_histories, return = "archive")
#' pp <- graphics::par(mfcol = c(2, 4))
#' pf_plot_history(dat_dcpf_histories, time_steps = 1:4,
#' add_particles = list(pch = 21, bg = "black"),
#' prompt = FALSE)
#' pf_plot_history(dat_dcpf_histories_connected, time_steps = 1:4,
#' add_particles = list(pch = 21, bg = "black"),
#' prompt = FALSE)
#' graphics::par(pp)
#'
#' @return The function returns a plot, for each time step, of all the possible locations of the individual, with sampled locations overlaid.
#'
#' @seealso \code{\link[flapper]{pf}} implements PF. \code{\link[flapper]{pf_simplify}} assembles paths from particle histories. \code{\link[flapper]{pf_plot_map}} creates an overall `probability of use' map from particle histories. \code{\link[flapper]{pf_plot_1d}}, \code{\link[flapper]{pf_plot_2d}} and \code{\link[flapper]{pf_plot_3d}} provide plotting routines for paths. \code{\link[flapper]{pf_loglik}} calculates the log-likelihood of each path.
Expand Down Expand Up @@ -172,28 +184,41 @@ pf_animate_history <-
#### pf_plot_map()

#' @title Plot `probability of use' from a PF algorithm
#' @description This function creates a plot of the `probability of use' across an area based on particles sampled by a particle filtering (PF) algorithm. To implement the function, a \code{\link[flapper]{pf_archive-class}} object that contains particles (locations) sampled by \code{\link[flapper]{pf}} must be supplied. The function extracts all sampled locations and, for each location, calculates `the probability of use' for that location over the time series. This is returned (invisibly) as a \code{\link[raster]{raster}} and plotted.
#' @param archive A \code{\link[flapper]{pf_archive-class}} object (from \code{\link[flapper]{pf}}).
#' @description This function creates a plot of the `probability of use' across an area based on particles sampled by a particle filtering (PF) algorithm. To implement the function, a \code{\link[flapper]{pf_archive-class}} object that contains connected particles (locations) sampled by \code{\link[flapper]{pf}} and processed by \code{\link[flapper]{pf_simplify}} must be supplied. The function extracts sampled locations and, for each location, calculates `the probability of use' for that location over the time series. This is returned (invisibly) as a \code{\link[raster]{raster}} and plotted.
#' @param archive A \code{\link[flapper]{pf_archive-class}} object (from \code{\link[flapper]{pf}} plus \code{\link[flapper]{pf_simplify}} with \code{record = "archive"}).
#' @param map A \code{\link[raster]{raster}} that defines a grid across the area of interest.
#' @param scale A character that defines how \code{\link[raster]{raster}} values are scaled: \code{"original"} uses the original values; \code{"max"} scales values by the maximum value so that they lie between zero and one; and \code{"sum"} scales values by their sum so that they sum to one.
#' @param transform (optional) A function to transform cell weights (e.g, \code{\link[base]{log}}).
#' @param scale A character that defines how \code{\link[raster]{raster}} values are scaled: \code{"original"} uses the original values; \code{"max"} scales values by the maximum value (so that, if \code{transform = NULL}, they lie between zero and one; and \code{"sum"} scales values by their sum so that they sum to one.
#' @param add_rasters A named list, passed to \code{\link[prettyGraphics]{pretty_map}}, to customise the appearance of the plotted surface.
#' @param ... Additional arguments passed to \code{\link[prettyGraphics]{pretty_map}}.
#'
#' @details For each location, the 'probability of use' is calculated as the sum of the number of times that the location was sampled, weighted by the associated probabilities of each sample.
#' @details For each location, the 'probability of use' is calculated as the sum of the number of times (time steps) that the location was sampled, weighted by the associated probabilities of each sample.
#'
#' @return The function invisibly returns a \code{\link[raster]{raster}}, in which each cell contains the `probability of use' score and produces a plot of this surface.
#'
#' @examples
#' #### Prepare data
#' # The example data 'dat_dcpf_histories' contains all particles sampled
#' # ... by an implementation of the DCPF algorithm. However, not all particles
#' # ... that were sampled at one time step may have been near to particles sampled
#' # ... at the next time step. In addition, some particles may have been sampled
#' # ... multiple times at one time step, but our maps of space use should reflect
#' # ... the number of time steps that the individual could have occupied a location,
#' # ... rather than the total number of samples of a location. Hence, to map
#' # ... space use, we should focus on the subset of particles that were connected
#' # ... between time steps and only retain one record of each particle at each time step
#' # ... using pf_simplify() with record = "archive"
#' dat_dcpf_histories_connected <- pf_simplify(dat_dcpf_histories, return = "archive")
#'
#' #### Example (1): Implement the function with default options
#' # using the example 'dat_dcpf_histories' data
#' pf_plot_map(dat_dcpf_histories, map = dat_dc$args$bathy)
#' pf_plot_map(dat_dcpf_histories_connected, map = dat_dc$args$bathy)
#'
#' #### Example (2): Re-scale the map
#' pf_plot_map(dat_dcpf_histories, map = dat_dc$args$bathy, scale = "max")
#' pf_plot_map(dat_dcpf_histories, map = dat_dc$args$bathy, scale = "sum")
#' pf_plot_map(dat_dcpf_histories_connected, map = dat_dc$args$bathy, scale = "max")
#' pf_plot_map(dat_dcpf_histories_connected, map = dat_dc$args$bathy, scale = "sum")
#'
#' #### Example (3): Customise the map
#' pf_plot_map(dat_dcpf_histories, map = dat_dc$args$bathy,
#' pf_plot_map(dat_dcpf_histories_connected, map = dat_dc$args$bathy,
#' add_rasters = list(col = grDevices::grey.colors(n = 100)),
#' xlab = "x", ylab = "y")
#'
Expand All @@ -203,6 +228,7 @@ pf_animate_history <-

pf_plot_map <- function(archive,
map,
transform = NULL,
scale = c("original", "max", "sum"),
add_rasters = list(),...){
# Check inputs
Expand All @@ -215,6 +241,11 @@ pf_plot_map <- function(archive,
wt_freq <- stats::aggregate(x = list("wt" = pf_particle_histories$pr_current),
by = list("id" = pf_particle_histories$id_current),
FUN = sum)
# Transform weighted frequencies
if(!is.null(transform)) {
wt_freq$wt <- transform(wt_freq$wt)
if(any(is.na(wt_freq$wt))) stop("'transform' function has created NAs.")
}
# Re-scale weighted frequencies e.g. so that the maximum value has a score of one
if(scale == "max"){
wt_freq$wt <- wt_freq$wt/max(wt_freq$wt)
Expand Down
17 changes: 11 additions & 6 deletions R/pf_classes.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
#### pf_archive-class

#' @title "pf_archive" class
#' @description An S3 class that defines the object returned by \code{\link[flapper]{pf}}.
#' @description An S3 class that defines the object returned by \code{\link[flapper]{pf}} or \code{\link[flapper]{pf}} plus \code{\link[flapper]{pf_simplify}} with the \code{return = "archive"} argument.
#'
#' @return This object is a named list, with two elements, which records the parameters used in the call to \code{\link[flapper]{pf}} and the particles sampled at each time step:
#' @return This object is a named list, with three elements, which records the particles sampled at each time step, the method and the parameters used in the call to \code{\link[flapper]{pf}}:
#'
#' \describe{
#' \item{args}{A named list that records the function arguments used to generate outputs. This is as inputted, but with the `calc_distance_graph' elements added if unsupplied and applicable.}
#' \item{history}{A list of dataframes, one for each time step, that record particle samples. Each dataframe comprises \code{n} rows (one for each particle) and the following five columns:}
#' \item{history}{A list of dataframes, one for each time step, that record particle samples. Each dataframe comprises \code{n} rows (one for each particle) and the following five columns:
#' \itemize{
#' \item{id_previous}{ An integer that uniquely defines a previous location on the \code{record} \code{\link[raster]{raster}}s. This is absent for the first time step. For subsequent time steps, this is \code{NA} if the fast Euclidean distances method has been used, which does not `remember' previous locations, but specified otherwise.)}
#' \item{pr_current}{ A double that defines the movement probabilities associated with previous locations. This is absent for the first time step. For subsequent time steps, this is \code{NA} if the fast Euclidean distances method has been used, which does not `remember' previous locations, but specified otherwise.}
Expand All @@ -19,7 +18,13 @@
#' }
#' }
#'
#' @seealso \code{\link[flapper]{dat_dcpf_histories}} provides an example of a \code{\link[flapper]{pf_archive-class}} object. \code{\link[flapper]{pf_simplify}} converts \code{\link[flapper]{pf_archive-class}} objects into \code{\link[flapper]{pf_path-class}} objects that comprise the reconstructed movement paths.
#' \item{method}{A character that defines whether or not \code{history} was derived directly from \code{\link[flapper]{pf}} (\code{method = "pf"}), in which case \code{history} contains all of the particles sampled at each time step, or via \code{\link[flapper]{pf}} plus \code{\link[flapper]{pf_simplify}} with \code{return = "archive"} (\code{method = "pf_simplify"}), in which case \code{history} contains the subset of particles at each time step that were re-sampled at the next time step; for particles that were sampled multiple times on a given time step, this only contains the most probable sample (see \code{\link[flapper]{pf_simplify}}).}
#'
#' \item{args}{A named list that records the function arguments passed to \code{\link[flapper]{pf}}. This is as inputted to \code{\link[flapper]{pf}}, but with the `calc_distance_graph' elements added if unsupplied and applicable.}
#'
#' }
#'
#' @seealso \code{\link[flapper]{dat_dcpf_histories}} provides an example of a \code{\link[flapper]{pf_archive-class}} object. \code{\link[flapper]{pf}} and \code{\link[flapper]{pf_simplify}} return \code{\link[flapper]{pf_archive-class}} objects. \code{\link[flapper]{pf_simplify}} can also convert \code{\link[flapper]{pf_archive-class}} objects into \code{\link[flapper]{pf_path-class}} objects that comprise the reconstructed movement paths.
#'
#' @author Edward Lavender
#' @docType package
Expand All @@ -32,7 +37,7 @@ NULL
#### pf_path-class

#' @title "pf" class
#' @description An S3 class that defines the object returned by \code{\link[flapper]{pf_simplify}}, following \code{\link[flapper]{pf}}.
#' @description An S3 class that defines the object returned by \code{\link[flapper]{pf_simplify}} with \code{return = "path"}, following \code{\link[flapper]{pf}}.
#'
#' @return A dataframe with that records the reconstructed paths. This includes a unique identifier for each path, the time step, the location (cell ID and three-dimensional coordinates) on the specified surface (e.g., \code{bathy}) and the probability associated with that cell, given movement from the previous cell, in the following columns:
#' \describe{
Expand Down
Loading

0 comments on commit e38985c

Please sign in to comment.