This functions identifies receivers with overlapping detection containers in space and time.
get_detection_containers_overlap(containers, services = NULL)
A SpatialPolygonsDataFrame
that defines detection containers (see get_detection_containers
). The data
slot must include a dataframe with the following columns: an unique, integer identifier for each receiver (`receiver_id') and receiver deployment Dates
(`receiver_start_date' and `receiver_end_date').
(optional) A dataframe that defines receiver IDs and servicing Dates
(times during the deployment period of a receiver when it was not active due to servicing). If provided, this must contain the following columns: an integer identifier for serviced receivers (named ‘receiver_id’) and two columns that define the time of the service(s) (‘service_start_date’ and ‘service_end_date’) (see make_matrix_receivers
).
The function returns a list with two elements:
overlap_by_receiver is list, with one element for all integers from 1:max(containers$receiver_id)
. Any elements that do not correspond to receivers contain a NULL element. List elements that correspond to receivers contain a dataframe that defines, for each day over the deployment period (defined in `timestamp') of that receiver (defined in `receiver_id'), whether (1) or not (0) that receiver overlapped in space with every other receiver (defined in the remaining columns by their receiver IDs).
overlap_by_date is a named list, with one element for each date from the start until the end of the study (min(containers$receiver_start_date):max(containers$receiver_end_date)
), that records an integer vector of all receivers with overlapping containers on that date. In this vector, each receiver overlaps with at least one other receiver (but not every receiver will necessarily overlap with every other receiver).
This function requires the tidyr-package
(specifically pivot_longer
).
get_detection_containers
creates detection containers.
#### Define receiver containers
## Define receiver locations as a SpatialPoints 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@data <- as.data.frame(xy)
rownames(xy@data) <- dat_moorings$receiver_id
## Get receiver-specific detection containers
# ... via get_detection_containers with byid = TRUE
containers <- get_detection_containers(xy, byid = TRUE)
#> Warning: GEOS support is provided by the sf and terra packages among others
## Link detection containers with receiver IDs and deployment dates
# ... in a SpatialPointsDataFrame, as required for this function.
containers_df <- dat_moorings[, c(
"receiver_id",
"receiver_start_date",
"receiver_end_date"
)]
row.names(containers_df) <- dat_moorings$receiver_id
containers <- sp::SpatialPolygonsDataFrame(containers, containers_df)
## Simulate some receiver 'servicing' dates for demonstration purposes
set.seed(1)
# Loop over each receiver...
services_by_receiver <- lapply(split(dat_moorings, 1:nrow(dat_moorings)), function(din) {
# For the receiver, simulate the number of servicing events
n <- sample(0:3, 1)
dout <- NULL
if (n > 0) {
# simulate the timing of servicing events
dates <- sample(seq(min(din$receiver_start_date), max(din$receiver_end_date), "days"), n)
dout <- data.frame(
receiver_id = rep(din$receiver_id, length(dates)),
service_start_date = dates,
service_end_date = dates
)
}
return(dout)
})
services <- do.call(rbind, services_by_receiver)
rownames(services) <- NULL
if (nrow(services) == 0) services <- NULL
#### Example (1): Implement function using containers alone
overlaps_1 <- get_detection_containers_overlap(containers = containers)
summary(overlaps_1)
#> Length Class Mode
#> list_by_receiver 57 -none- list
#> list_by_date 457 -none- list
#### Example (2): Account for servicing dates
overlaps_2 <- get_detection_containers_overlap(
containers = containers,
services = services
)
# Examine the first few simulated servicing events
services[1:3, ]
#> receiver_id service_start_date service_end_date
#> 1 4 2016-08-16 2016-08-16
#> 2 4 2016-07-09 2016-07-09
#> 3 4 2016-12-26 2016-12-26
# Show that the list_by_date element for the first servicing event
# ... includes the first receiver in services$receiver_id
# ... for overlaps_1 but not overlaps_2,
# ... which accounts for that fact that the receiver was serviced then:
overlaps_1$list_by_date[[as.character(services$service_start_date[1])]]
#> [1] 3 9 12 40 4 24 23 26 20 18 21 31
overlaps_2$list_by_date[[as.character(services$service_start_date[1])]]
#> [1] 3 9 24 23 26 20 18 21 31
# Likewise, show that the list_by_receiver element for that receiver
# ... includes overlapping receivers in overlaps_1 but not overlaps_2:
r_id <- services$receiver_id[1]
overlaps_1$list_by_receiver[[r_id]][overlaps_1$list_by_receiver[[r_id]]$timestamp %in%
services$service_start_date[services$receiver_id == r_id], ]
#> timestamp receiver_id 3 7 9 11 12 14 18 20 21 23 24 26 27 29 30 31
#> 2016-07-09 2016-07-09 4 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
#> 2016-08-16 2016-08-16 4 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
#> 2016-12-26 2016-12-26 4 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
#> 33 35 36 37 38 39 40 41 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
#> 2016-07-09 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#> 2016-08-16 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#> 2016-12-26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
overlaps_2$list_by_receiver[[r_id]][overlaps_2$list_by_receiver[[r_id]]$timestamp %in%
services$service_start_date[services$receiver_id == r_id], ]
#> timestamp receiver_id 3 7 9 11 12 14 18 20 21 23 24 26 27 29 30 31
#> 2016-07-09 2016-07-09 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#> 2016-08-16 2016-08-16 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#> 2016-12-26 2016-12-26 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#> 33 35 36 37 38 39 40 41 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
#> 2016-07-09 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#> 2016-08-16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#> 2016-12-26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0