map_dens()
creates a smoothed utilisation distribution (UD).
Usage
as.im.SpatRaster(.map)
as.owin.SpatRaster(.map, .im = NULL)
as.owin.sf(.poly, .bbox = sf::st_bbox(.poly), .invert = TRUE)
bw.h(X)
map_dens(
.map,
.owin = as.owin.SpatRaster(.map),
.coord = NULL,
.discretise = FALSE,
.shortcut = list(),
.sigma = bw.h,
...,
.fterra = FALSE,
.plot = TRUE,
.tryCatch = TRUE,
.verbose = getOption("patter.verbose")
)
Arguments
- .map
A
terra::SpatRaster
that defines the grid on which the UD is represented. If.coord = NULL
,.map
also defines the points (and associated weights) that are smoothed (see.map_coord()
). The coordinate reference system of.map
must be planar and specified.- .im, .owin
A pixel image representation of
.map
(seeas.im.SpatRaster()
andspatstat.geom::im()
) and an observation window (seeas.owin.SpatRaster()
,as.owin.sf()
andspatstat.geom::owin()
). If un-supplied,.owin
is defined automatically from.map
viaas.owin.SpatRaster()
, which usesas.im.SpatRaster()
internally (see Details). For faster results, use a rectangular or polygon observation window (seeas.owin.sf()
).- .poly, .bbox, .invert
For
as.owin.sf()
to construct observation windows fromsf
objects..poly
is ansf
polygon object;.bbox
is the bounding of a simple feature (seesf::st_bbox()
);.invert
is a logical variable that defines whether or not to invert.poly
(e.g., to turn a terrestrial polygon into an aquatic polygon);
- .coord
(optional) Coordinates for density estimation, provided in any format accepted by
.map_coord()
. Coordinates must be planar.- .discretise
If
.coord
is provided,.discretise
is alogical
variable that defines whether or not to discretise coordinates on.map
(see.map_coord()
).- .shortcut
(optional) A named
list
from a previous call tomap_dens()
. If supplied, the function short-cuts straight to smoothing (.owin
,.coord
and.discretise
are silently unused).- .sigma, X
.sigma
is anumeric
value or afunction
that specifies the smoothing bandwidth (passed tospatstat.explore::density.ppp()
'ssigma
argument). The default option isbw.h()
, which sets the bandwidth based on combined variance of summarised coordinates, formatted as a point patternX
(seespatstat.geom::ppp
), using the ad-hoc method (Worton, 1989). Seespatstat
functions (e.g.,spatstat.explore::bw.diggle()
) for more sophisticated methods.- ...
Arguments for density estimation, passed to
spatstat.explore::density.ppp()
, such assigma
(i.e., the bandwidth).at
andse
are not permitted.- .fterra
A
logical
variable that defines whether or not to paralleliseterra::resample()
.- .plot
A
logical
variable that defines whether or not to plot the output.- .tryCatch
A
logical
variable that controls error handling:If
.tryCatch = FALSE
, if density estimation fails with an error, the function fails with the same error.If
.tryCatch = TRUE
, if density estimation fails with an error, the function produces a warning with the error message and returnsNULL
.
- .verbose
User output control (see
patter-progress
for supported options).
Value
The function returns a named list
, with the following elements:
x
: aspatstat.geom::ppp
object that defines points for density estimation;D
: aspatstat.geom::im
object of estimated intensities, fromspatstat.explore::density.ppp()
;ud
: a normalisedterra::SpatRaster
;
D
and ud
are NULL
if spatstat.explore::density.ppp()
fails and .tryCatch = TRUE
.
Details
map_dens()
smooths (a) a terra::SpatRaster
or (b) a set of inputted coordinates.
.map_coord()
(and .map_mark()
) are used to define coordinates and weights:
If
.coords
isNULL
,.map
cell coordinates are used for density estimation and cell values are used as weights.If coordinates are supplied, coordinates are optionally re-expressed on
.map
and then used for density estimation. This option is generally faster. Coordinate weights are defined by.map_mark()
.
Cell coordinates and associated weights are converted to a spatstat.geom::ppp()
object, which is passed, alongside the observation window (.owin
), to spatstat.explore::density.ppp()
for the estimation. Weights must sum to one.
as.im.SpatRaster()
, as.owin.SpatRaster()
and as.owin.sf()
are helper functions that convert a terra::SpatRaster
to a pixel image and an observation window (see spatstat.geom::owin()
). as.im.SpatRaster()
is based on maptools::as.im.RasterLayer()
. as.owin.SpatRaster()
either defines a rectangular window, if there are no NAs on .map
, or converts .map
directly to an owin
object. Gridded observation windows, especially if high resolution, considerably slow down density estimation and may exhaust vector memory. Use rectangular windows, or convert sf
objects to polygon windows (via as.owin.sf()
) if possible.
If .shortcut
is supplied, the preceding steps can be skipped and the function short-cuts straight to smoothing. Use this option if the preceding steps are slow and you want to trial different smoothing options (such as sigma
functions).
Coordinates and associated weights are smoothed via spatstat.explore::density.ppp()
into an image. Pixel resolution and smoothing parameters such as bandwidth can be controlled via ...
arguments which are passed directly to this function. The default bandwidth is set via bw.h()
(see .sigma
). The output is translated into a gridded probability density surface (on the geometry defined by .map
). This process may use terra::resample()
, which can be parallelised via .fterra
(which controls the threads
argument of that function).
This function replaces flapper::kud*()
and flapper::pf_kud*()
routines based on adehabitatHR
(see here).
On Linux, these functions cannot be used within a Julia
session.
References
Worton, B. J. (1989). Kernel Methods for Estimating the Utilization Distribution in Home-Range Studies. Ecology 70, 164–168. doi: 10.2307/1938423
See also
map_*()
functions build maps of space use:
map_pou()
maps probability-of-use;map_dens()
maps point density;map_hr
_*()
functions map home ranges;
All maps are represented as terra::SpatRaster
s.
To derive coordinates for mapping patterns of space use for tagged animals, see:
coa()
to calculate centre-of-activity;pf_filter()
and associates to sample locations using particle filtering;
Examples
if (patter_run(.julia = FALSE, .geospatial = TRUE)) {
library(data.table)
library(dtplyr)
library(dplyr, warn.conflicts = FALSE)
library(spatstat.explore)
#### Define map
map <- dat_gebco()
#### Example (1): Use sample coordinates
# Sample example coordinates
coord <-
map |>
terra::spatSample(size = 100L, xy = TRUE, cell = TRUE, na.rm = TRUE) |>
select("x", "y") |>
as.data.table()
# Use x, y coordinates
map_dens(map, .coord = coord)
# Other formats are acceptable
map_dens(map, .coord = as.matrix(coord))
map_dens(map, .coord = as.data.frame(coord))
# `cell_x` and `cell_y` coordinates are acceptable
map_dens(map, .coord = coord[, .(cell_x = x, cell_y = y)])
# A SpatRaster is also acceptable
pou <- map_pou(map, .coord = coord, .plot = FALSE)$ud
map_dens(pou)
#### Example (2): Use coordinates from `sim_path_walk()`
coord <- dat_path()
map_dens(map, .coord = coord)
points(coord$x, coord$y, cex = 0.5)
#### Example (3): Use coordinates from `coa()`
# Use example dataset
coord <- dat_coa()
map_dens(map, .coord = coord)
points(coord$x, coord$y, cex = 0.5)
#### Example (4): Use a time series of coordinates from `pf_*()`
# Use example dataset
# * We use particles from the forward filter (`?pf_filter()`);
# * Particles are equally weighted b/c re-sampling is implemented every time step;
# * It is better to use outputs from the particle smoother;
coord <- dat_pff()$states
map_dens(map, .coord = coord)
# points(coord$x, coord$y, cex = 0.5)
#### Example (5): Control smoothing via `spatstat.explore::density.ppp()`
# E.g. use fixed bandwidth:
map_dens(map, .coord = coord, .sigma = 5)
map_dens(map, .coord = coord, .sigma = 100)
# E.g., perform automatic bandwidth selection using cross validation:
if (FALSE) {
# These examples are slow
map_dens(map, .coord = coord, .sigma = bw.diggle) # 2 s
map_dens(map, .coord = coord, .sigma = bw.scott) # 1 s
map_dens(map, .coord = coord, .sigma = bw.ppl) # 65 s
map_dens(map, .coord = coord, .sigma = bw.CvL) # 25 s
}
}
#> Loading required package: spatstat.data
#> Loading required package: spatstat.univar
#> spatstat.univar 3.1-2
#> Loading required package: spatstat.geom
#> spatstat.geom 3.3-6
#>
#> Attaching package: ‘spatstat.geom’
#> The following object is masked from ‘package:data.table’:
#>
#> shift
#> Loading required package: spatstat.random
#> spatstat.random 3.3-3
#> Loading required package: nlme
#>
#> Attaching package: ‘nlme’
#> The following object is masked from ‘package:dplyr’:
#>
#> collapse
#> spatstat.explore 3.4-2
#> `patter::map_dens()` called @ 2025-04-22 09:30:56...
#> ... 09:30:56: Processing `.map`...
#> ... 09:30:56: Building XYM...
#> ... 09:30:56: Defining `ppp` object...
#> Observation window is gridded.
#> ... 09:30:56: Estimating density surface...
#> ... 09:30:56: Scaling density surface...
#> `patter::map_dens()` call ended @ 2025-04-22 09:30:56 (duration: ~0 sec(s)).
#> `patter::map_dens()` called @ 2025-04-22 09:30:56...
#> ... 09:30:56: Processing `.map`...
#> ... 09:30:56: Building XYM...
#> ... 09:30:56: Defining `ppp` object...
#> Observation window is gridded.
#> ... 09:30:56: Estimating density surface...
#> ... 09:30:56: Scaling density surface...
#> `patter::map_dens()` call ended @ 2025-04-22 09:30:56 (duration: ~0 sec(s)).
#> `patter::map_dens()` called @ 2025-04-22 09:30:56...
#> ... 09:30:56: Processing `.map`...
#> ... 09:30:56: Building XYM...
#> ... 09:30:56: Defining `ppp` object...
#> Observation window is gridded.
#> ... 09:30:56: Estimating density surface...
#> ... 09:30:56: Scaling density surface...
#> `patter::map_dens()` call ended @ 2025-04-22 09:30:57 (duration: ~1 sec(s)).
#> `patter::map_dens()` called @ 2025-04-22 09:30:57...
#> ... 09:30:57: Processing `.map`...
#> ... 09:30:57: Building XYM...
#> ... 09:30:57: Defining `ppp` object...
#> Observation window is gridded.
#> ... 09:30:57: Estimating density surface...
#> ... 09:30:57: Scaling density surface...
#> `patter::map_dens()` call ended @ 2025-04-22 09:30:57 (duration: ~0 sec(s)).
#> `patter::map_pou()` called @ 2025-04-22 09:30:57...
#> ... Building XYM...
#> ... Building SpatRaster...
#> `patter::map_pou()` call ended @ 2025-04-22 09:30:57 (duration: ~0 sec(s)).
#> `patter::map_dens()` called @ 2025-04-22 09:30:57...
#> ... 09:30:57: Processing `.map`...
#> ... 09:30:57: Building XYM...
#> ... 09:30:57: Defining `ppp` object...
#> Observation window is gridded.
#> ... 09:30:57: Estimating density surface...
#> ... 09:30:57: Scaling density surface...
#> `patter::map_dens()` call ended @ 2025-04-22 09:30:57 (duration: ~0 sec(s)).
#> `patter::map_dens()` called @ 2025-04-22 09:30:57...
#> ... 09:30:57: Processing `.map`...
#> ... 09:30:57: Building XYM...
#> ... 09:30:57: Defining `ppp` object...
#> Observation window is gridded.
#> ... 09:30:57: Estimating density surface...
#> ... 09:30:57: Scaling density surface...
#> `patter::map_dens()` call ended @ 2025-04-22 09:30:57 (duration: ~0 sec(s)).
#> `patter::map_dens()` called @ 2025-04-22 09:30:57...
#> ... 09:30:57: Processing `.map`...
#> ... 09:30:57: Building XYM...
#> ... 09:30:57: Defining `ppp` object...
#> Observation window is gridded.
#> ... 09:30:57: Estimating density surface...
#> ... 09:30:57: Scaling density surface...
#> `patter::map_dens()` call ended @ 2025-04-22 09:30:57 (duration: ~0 sec(s)).
#> `patter::map_dens()` called @ 2025-04-22 09:30:57...
#> ... 09:30:57: Processing `.map`...
#> ... 09:30:57: Building XYM...
#> ... 09:30:57: Defining `ppp` object...
#> Observation window is gridded.
#> ... 09:30:57: Estimating density surface...
#> ... 09:30:57: Scaling density surface...
#> `patter::map_dens()` call ended @ 2025-04-22 09:30:57 (duration: ~0 sec(s)).
#> `patter::map_dens()` called @ 2025-04-22 09:30:57...
#> ... 09:30:57: Processing `.map`...
#> ... 09:30:57: Building XYM...
#> ... 09:30:58: Defining `ppp` object...
#> Observation window is gridded.
#> ... 09:30:58: Estimating density surface...
#> ... 09:30:58: Scaling density surface...
#> `patter::map_dens()` call ended @ 2025-04-22 09:30:58 (duration: ~1 sec(s)).
#> `patter::map_dens()` called @ 2025-04-22 09:30:58...
#> ... 09:30:58: Processing `.map`...
#> ... 09:30:58: Building XYM...
#> ... 09:30:58: Defining `ppp` object...
#> Observation window is gridded.
#> ... 09:30:58: Estimating density surface...
#> ... 09:30:58: Scaling density surface...
#> `patter::map_dens()` call ended @ 2025-04-22 09:30:58 (duration: ~0 sec(s)).