View source: R/calc_zoi_cumulative.R
calc_zoi_cumulative | R Documentation |
This function takes in a raster with locations or counts of
infrastructure
and calculates a raster (or set of rasters, in case there is more the one
value for radius
) representing the cumulative zone of influence (ZOI)
or density of features in space. The process is done through a spatial
filter/moving window/neighborhood analysis. The zones of influence
(or weight matrices) are defined by functions that decay with the distance
from each infrastructure feature and their rate of decay is controlled by the
ZOI radius (radius
), which defines how far the influence of an infrastructure
feature goes. By using moving window analyses, the cumulative ZOI account for
the sum of the influence of multiple features across space, weighted by
the distance to these features according the the ZOI shape.
For more details on the ZOI functions, see zoi_functions()
.
The procedure might be computed in both R and GRASS GIS. In R, the
neighborhood analysis is done with the terra::focal()
function. In GRASS,
different modules might be used for the computation: r.resamp.filter
,
r.mfilter
, or r.neighbors
. See details for their differences. In GRASS, it
requires an active connection between the R session and a GRASS GIS
location and mapset (through the package rgrass), and that the input
maps are already loaded within this GRASS GIS mapset.
If the calculations are done in R, the input is a (set of) raster map(s)
and the function returns another (set of) raster map(s). If the calculations
are done within GRASS GIS, the input is the name of a raster map already
loaded in a GRASS GIS location and mapset, and the function returns
only the name of the output map. This map is stored in the the GRASS GIS
location/mapset, and might be retrieved to R through the
rgrass::read_RAST()
function or exported outside GRASS using the
r.out.gdal
module, for instance.
calc_zoi_cumulative(
x,
radius = 100,
type = c("circle", "Gauss", "rectangle", "exp_decay", "bartlett", "threshold",
"mfilter")[1],
where = c("R", "GRASS")[1],
output_type = c("cumulative_zoi", "density")[1],
zoi_limit = 0.05,
min_intensity = 0.01,
max_dist = 50000,
zeroAsNA = FALSE,
extent_x_cut = NULL,
extent_y_cut = NULL,
na.policy = "omit",
na.rm = TRUE,
g_module = c("r.mfilter", "r.resamp.filter", "r.neighbors")[1],
g_parallel = TRUE,
g_output_map_name = NULL,
g_input_as_region = FALSE,
g_remove_intermediate = TRUE,
g_overwrite = FALSE,
verbose = FALSE,
...
)
x |
Notice that, different from |
radius |
|
type |
|
where |
|
output_type |
|
zoi_limit |
|
min_intensity |
|
max_dist |
|
zeroAsNA |
|
extent_x_cut , entent_y_cut |
|
na.policy |
|
na.rm |
|
g_module |
|
g_parallel |
|
g_output_map_name |
|
g_input_as_region |
|
g_remove_intermediate |
|
g_overwrite |
|
verbose |
|
... |
Other arguments to be used within |
If the calculations are performed in R (where = "R"
),
a RasterLayer
or SpatRaster (according to the input x
map)
with the cumulative zone of influence or density of features. While the
cumulative ZOI uses a ZOI/weight matrix rescaled to 1 at the central pixel
(creating values in the output map which might go well beyond 1), the
density of features uses a normalized ZOI/weight matrix (with all values
summing 1), what created values smaller than one in the output map.
if multiple radius
values are given, a RasterBrick
or multi-layer
SpatRaster
, with the cumulative ZOI or density maps for each ZOI radius.
If the computation is done in GRASS GIS, the output is the name of
the output raster map(s) within the GRASS GIS location and mapset of the
current session. The user can retrieve these maps to R using
rgrass::read_RAST()
or export them outside GRASS using the
r.out.gdal
module, for instance.
The input raster is supposed to represent the location of point, line, or polygon infrastructure (e.g. houses, roads, mining areas), but any landscape variable whose representation might be one of those would fit here (e.g. areas of forest or any other habitat type or land cover). We recommend that the input raster has a metric projection, so that distances and zones of influence are based on distance to infrastructure measured in meters.
The neighborhood analysis to define the cumulative ZOI can be computed with different functions/filters. The options currently implemented are:
circular/threshold matrix: the circular filter (type = "circle"
or
type = "threshold"
or type = "step"
) is a matrix with constant weights
in which the parameter radius
corresponds to the radius of the circle
centered on the central pixel. It is similar to a circular buffer matrix.
Gaussian matrix: the Gaussian filter (type = "Gauss"
or type = "gauss"
or type = "gaussian_decay"
) is a matrix with weights following a Gaussian
or Normal decay. The Gaussian curve is 1 at the central cell and
is parameterized on the radius
and
the zoi_limit
, which controls how fast the curve decreases with distance.
See zoi_functions()
for details.
Exponential decay matrix: the exponential decay filter
(type = "exp_decay"
) is a matrix with weights following an exponential
decay curve, with value 1 in the central cell and
parameterized on the radius
and the zoi_limit
.
See zoi_functions()
for details.
Rectangular matrix: the rectangular filter (type = "rectangle"
or type = "box"
) is
a weight matrix whose shape is a square of dimensions n
x n
,
with n = 2 * radius
.
Bartlett or linear decay matrix: the Bartlett, linear, or tent decay filter
(type = "bartlett"
or type = "linear_decay"
or type = "tent_decay"
)
is a weight matrix whose value is 1 in the central cell and whose weights
decrease linearly up to zero at a distance equals radius
.
See zoi_functions()
for details.
user-customized filter: if type = "mfilter"
, radius
is not
numeric but should be a user-defined matrix of weights. Examples are ones
created through filter_create()
, terra::focalMat()
,
smoothie::kernel2dmeitsjer()
, or matrices created by hand.
Weight matrices might differ from the expected decay function depending on the intended resolution - the finer the resolution, the more detailed and correspondent to the original functions the matrix will be.
In GRASS GIS, different modules might be used for the computation,
r.resamp.filter
, r.mfilter
, or r.neighbors
. The module to be used is
controlled by the parameter g_module
. These algorithms provide different
capabilities and flexibility.
r.resamp.filter
seems to be the fastest one
in most cases, but has less flexibility in the choice of the zone of influence
function. The algorithm calculates the weighted density of features, which
might be rescaled to the cumulative ZOI if the appropriate scaling factor
(calculated from the weight matrix) is provided. Currently only the
filters type = "bartlett"
and type = "box"
are implemented. More
information about the algorithm
here.
r.mfilter
is slower than r.resamp.filter
but much faster than
r.neighbors
, and allows a flexible choice of the shape of the zone of
influence (the wight matrix shape). r.mfilter
is then the most indicated
in terms of a balance between flexibility in the choice of the ZOI shape
and computation efficiency.
The only inconvenient of r.mfilter
is that it
creates an edge effect with no information in the outer cells of a raster
(the number of cells correspond to radius
or half the size of the weight
matrix), so if it is used the users should add a buffer area
= radius around the input raster map, to avoid such edge effects.See https://github.com/OSGeo/grass/issues/2184 for more details.
r.neighbors
is considerably slower than the other algorithms (from 10 to
100 times), but allows a flexible choice of the ZOI shape. Contrary to
r.resamp.filter
and r.mfilter
, which can only perform a sum of pixel
values weighted by the input filter or ZOI, r.neighbors
might
calculate many other statistical summaries within the window of analysis,
such as mean, median, standard deviation etc.
See zoi_functions()
for some ZOI function shapes and
filter_create()
for options to create weight matrices.
See also smoothie::kernel2dmeitsjer()
, terra::focalMat()
, and
raster::focalWeight()
for other functions to create filters or weight matrices.
See
r.mfilter,
r.resamp.filter, and
r.neighbors for
GRASS GIS implementations of neighborhood analysis.
See calc_zoi_nearest()
for the computation of the zone of influence
of the nearest feature only.
# Running calc_zoi_cumulative through R
library(terra)
# Load raster data
f <- system.file("raster/sample_area_cabins_count.tif", package = "oneimpact")
cabins <- terra::rast(f)
# calculate cumulative zone of influence for multiple influence radii,
# using a Gaussian filter
zoi_values <- c(250, 500, 1000, 2500, 5000)
cumzoi_gauss <- calc_zoi_cumulative(cabins, type = "Gauss", radius = zoi_values)
plot(cumzoi_gauss)
# calculate cumulative zone of influence for multiple influence radii,
# using a circle neighborhood
cumzoi_circle <- calc_zoi_cumulative(cabins, type = "circle", radius = zoi_values)
plot(cumzoi_circle)
# calculate cumulative zone of influence for multiple influence radii,
# using an exponential decay neighborhood
cumzoi_exp <- calc_zoi_cumulative(cabins, type = "exp_decay", radius = zoi_values)
plot(cumzoi_exp)
# comparing
plot(c(cumzoi_gauss[[3]], cumzoi_circle[[3]], cumzoi_exp[[3]]),
main = c("Gaussian 1000m",
"Circle 1000m",
"Exponential decay 1000m"))
# calculate cumulative influence for a single zone of influence
# using a user-defined filter
my_filter <- filter_create(cabins, radius = 1000, type = "rectangle")
cumzoi_user <- calc_zoi_cumulative(cabins, type = "mfilter", radius = my_filter)
plot(cumzoi_user, main = "User-defined rectangular filter")
# calculate density with 1000m radius using an exp_decay neighborhood
density_exp <- calc_zoi_cumulative(cabins, type = "exp_decay", radius = 1000,
output_type = "density")
# compare
# note the difference in the color scales
plot(c(cumzoi_exp[[3]], density_exp),
main = c("Cumulative ZoI 1000m", "Density 1000m"))
#--------------------
# Running calc_zoi_cumulative through GRASS GIS
library(rgrass)
library(terra)
# Load raster data
f <- system.file("raster/sample_area_cabins.tif", package = "oneimpact")
cabins <- terra::rast(f)
# connect to grass gis and create grass location
# For linux or within OSGeo4W shell
grassdir <- system("grass --config path", intern = TRUE)
# grassdir <- system("grass78 --config path", intern = TRUE) # for GRASS 7.8
# If you used the standalone installer in Windows
# grassdir <- "C:\Programs\GRASS GIS 7.8" # Correct if the path GRASS version or path is different
gisDB <- "." # create location and mapset in the working directory
loc <- "ETRS_33N/" # name of the location
ms <- "PERMANENT" # name of the mapset
rgrass::initGRASS(gisBase = grassdir,
SG = cabins, # use map to define location projection
home = tempdir(),
override = TRUE,
gisDbase = gisDB,
location = loc,
mapset = ms)
# define map name within GRASS GIS
cabins_g <- "cabins_example"
# add file to GRASS GIS mapset
rgrass::write_RAST(cabins, cabins_g, flags = c("o", "overwrite"))
# check
terra::plot(cabins, col = "black",
main = "Map of tourist cabins")
#---
# define region in GRASS GIS
rgrass::execGRASS("g.region", raster = cabins_g,
flags = "p")
#---
# Guarantee input map is binary (zeros as background)
# Input map name within GRASS GIS - binary map
cabins_bin_g <- grass_binarize(cabins_g, breaks = 1, output = "cabins_example_bin",
null = 0, overwrite = TRUE)
# check input
cabins_bin <- rgrass::read_RAST("cabins_example_bin", return_format = "terra", NODATA = 255)
plot(cabins_bin, col = c("lightyellow", "black"),
main = "Binarized map of cabins")
#---
# Using 'r.mfilter' algorithm (default)
# Exponential decay
exp_name <- calc_zoi_cumulative(x = cabins_bin_g,
radius = 1000, zoi_limit = 0.01,
type = "exp_decay",
where = "GRASS",
g_overwrite = TRUE,
verbose = TRUE)
# Bartlett decay
barlett_name <- calc_zoi_cumulative(x = cabins_bin_g,
radius = 1000,
type = "bartlett",
where = "GRASS",
g_overwrite = TRUE,
verbose = TRUE)
# Gaussian decay
gauss_name <- calc_zoi_cumulative(x = cabins_bin_g,
radius = 1000, zoi_limit = 0.01,
type = "Gauss",
where = "GRASS",
g_overwrite = TRUE,
verbose = TRUE)
# Threshold decay (circle, step)
threshold_name <- calc_zoi_cumulative(x = cabins_bin_g,
radius = 1000,
type = "threshold",
where = "GRASS",
g_overwrite = TRUE,
verbose = TRUE)
(all_names <- c(exp_name, barlett_name, gauss_name, threshold_name))
# visualize
cabins_zoi_cumulative <- rgrass::read_RAST(all_names, return_format = "terra")
title_plot <- c("Exponential decay 1000m", "Bartlett decay 1000m",
"Gaussian decay 1000m", "Threshold decay 1000m")
terra::plot(cabins_zoi_cumulative, main = title_plot)
#---
# calculate density vs cumulative ZoI
exp_name_d <- calc_zoi_cumulative(x = cabins_bin_g,
radius = 1000, zoi_limit = 0.01,
type = "exp_decay", output_type = "density",
where = "GRASS",
g_overwrite = TRUE,
verbose = TRUE)
cabins_density <- rgrass::read_RAST(exp_name_d, return_format = "terra")
terra::plot(c(cabins_zoi_cumulative[[1]], cabins_density),
main = c("Cumulative ZoI", "Density"))
#---
# Using 'r.resamp.filter' algorithm
# rectangle
rectangle_resamp_filt <- calc_zoi_cumulative(x = cabins_bin_g,
radius = 1000,
type = "box",
output_type = "density",
where = "GRASS",
g_module = "r.resamp.filter",
g_overwrite = TRUE,
verbose = TRUE)
rgrass::read_RAST(rectangle_resamp_filt, return_format = "terra") |>
plot(main = "Rectangle ZoI 1000m")
# bartlett
bartlett_resamp_filt <- calc_zoi_cumulative(x = cabins_bin_g,
radius = 1000,
type = "bartlett",
output_type = "cumulative_zoi",
where = "GRASS",
g_module = "r.resamp.filter",
g_overwrite = TRUE,
verbose = TRUE)
rgrass::read_RAST(bartlett_resamp_filt, return_format = "terra") |>
plot(main = "Bartlett ZoI 1000m")
# not run
# Gaussian - to be implemented!
## Not run:
gauss_resamp_filt <- calc_zoi_cumulative(x = cabins_bin_g,
radius = "1000,3000",
type = "gauss,box",
output_type = "cumulative_zoi",
where = "GRASS",
module = "r.resamp.filter",
overwrite = TRUE, quiet = FALSE)
rgrass::read_RAST(bartlett_resamp_filt, return_format = "terra") |>
plot()
## End(Not run)
# remove rasters created
# to_remove_rast <- unique(c(all_names, exp_name_d,
# rectangle_resamp_filt, bartlett_resamp_filt))
# rgrass::execGRASS("g.remove", type = "vect", name = to_remove_vect, flags = "f")
# rgrass::execGRASS("g.remove", type = "rast", name = to_remove_rast, flags = "f")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.