% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/calculate_indices.R
\name{calculate_indices}
\alias{calculate_indices}
\title{Calculate indices from the bands of a raster}
\usage{
calculate_indices(
  raster,
  indices,
  output_filename,
  ...,
  cores = 1L,
  wopt = list(),
  overwrite = FALSE,
  extra_objects = list(),
  names_suffix = NULL
)
}
\arguments{
\item{raster}{The raster (either as a SpatRaster or object readable by
\code{\link[terra:rast]{terra::rast()}}) to compute indices from.}

\item{indices}{A data frame of indices to compute. The intent is for this
function to work with subsets of \code{\link[=spectral_indices]{spectral_indices()}}, but you can provide
any data frame with \code{formula}, \code{bands}, and \code{short_name} columns; see
"Custom indices" below.}

\item{output_filename}{The filename to write the computed metrics to.}

\item{...}{These dots are for future extensions and must be empty.}

\item{cores}{positive integer. If \code{cores > 1}, a 'parallel' package cluster with that many cores is created and used}

\item{wopt}{list with named options for writing files as in \code{\link[terra]{writeRaster}}}

\item{overwrite}{logical. If \code{TRUE}, \code{filename} is overwritten}

\item{extra_objects}{A named list of additional objects to pass to the
minimal environment that formulas are executed in. For instance, if you
need to use the \code{pmax} function in order to calculate an index, you can
make it available in the environment by setting
\code{extra_objects = list("pmax" = pmax)}. Providing extra functionality is
inherently less safe than the default minimal environment, and as such always
emits a warning, which you can suppress with \code{suppressWarnings()}.}

\item{names_suffix}{If not \code{NULL}, will be used (with \code{\link[=paste]{paste()}}) to add a
suffix to each of the band names returned.}
}
\value{
\code{output_filename}, unchanged.
}
\description{
This function computes any number of indices from an input raster via
\code{\link[terra:predict]{terra::predict()}}. By default, this function is designed to work with
subsets of \code{\link[=spectral_indices]{spectral_indices()}}, but it will work with any data frame with a
\code{formula}, \code{bands}, and \code{short_name} column.
}
\section{Security}{

Note that this function is running code from the \code{formula} column of the
spectral indices data frame, which is derived from a JSON file downloaded off
the internet. It's not impossible that an attacker could take advantage of
this to run arbitrary code on your computer. To mitigate this, indices are
calculated in a minimal environment that contains very few functions or
symbols (preventing an attacker from accessing, for example, \code{system()}).

Still, it's good practice to inspect your \code{formula} column to make sure
there's nothing nasty hiding in any of the formulas you're going to run.
Additionally, consider using pre-saved indices tables or
\code{spectral_indices(download_indices = FALSE)} if using this in an unsupervised
workload.
}

\section{Custom indices}{

While this function is designed to work with subsets of \code{\link[=spectral_indices]{spectral_indices()}},
you can also provide your own custom indices by providing a data frame with
at least three columns:
\itemize{
\item \code{formula} should contain a string representation of the equation used to
calculate the index. This string will be interpreted as R code, and should use
normal R arithmetic operators. Any additional functions used in calculating the
index will need to be passed through \code{extra_objects}.
\item \code{bands} should be a list column containing character vectors identifying the
bands required to calculate the index. These vectors will be checked against the
band names of \code{raster} to make sure that all necessary bands are available
before indices are calculated.
\item \code{short_name} should contain a string which will be used as the band name in
the final output file.
}

Sometimes you might want to tweak the formula used for an existing index, for
instance to set non-data parameters to constant values. In that case, make sure
you also update \code{bands} to reflect just the bands required by your updated formula,
so that the function won't error unnecessarily.
}

\examples{
our_raster <- system.file("rasters/example_sentinel1.tif", package = "rsi")
calculate_indices(
  our_raster,
  filter_bands(bands = names(terra::rast(our_raster))),
  tempfile(fileext = ".tif"),
  names_suffix = "sentinel1"
)

# Formulas aren't able to access most R functions or operators,
# in order to try and keep formulas from doing something bad:
example_indices <- filter_platforms(platforms = "Sentinel-1 (Dual Polarisation VV-VH)")[1, ]
example_indices$formula <- 'system("echo something bad")'
# So this will error:
try(
  calculate_indices(
    system.file("rasters/example_sentinel1.tif", package = "rsi"),
    example_indices,
    tempfile(fileext = ".tif")
  )
)

# Because of this, formulas which try to use most R functions
# will wind up erroring as well:
example_indices$formula <- "pmax(VH, VV)"
try(
  calculate_indices(
    system.file("rasters/example_sentinel1.tif", package = "rsi"),
    example_indices,
    tempfile(fileext = ".tif")
  )
)

# To fix this, pass the objects you want to use to `extra_objects`
calculate_indices(
  system.file("rasters/example_sentinel1.tif", package = "rsi"),
  example_indices,
  tempfile(fileext = ".tif"),
  extra_objects = list(pmax = pmax)
) |>
  suppressWarnings(classes = "rsi_extra_objects")

}
