#' Remove rasters and vectors from the GRASS cache
#'
#' @description **fasterRaster** functions attempt to delete rasters and vectors in the **GRASS** cache, but not all intermediate files can be removed. This function can be used to clear the cache of extraneous rasters and vectors.
#'
#' Calling this function inside another function's environment and defining `x` as `"*"` can be very **dangerous**, as it will detect objects outside of that environment, and thus delete any rasters/vectors outside that environment. Here is a guide:
#' * To delete files associated with a single `GRaster` or `GVector`, use `mow(GRaster_to_unlink)` or `mow(GVector_to_unlink)`.
#' * To delete files associated with more than one `GRaster`s and/or `GVector`s, provide them as a list. For example, use `mow(list(GRaster_to_unlink, GVector_to_unlink))`.
#' * To remove all rasters, all vectors, or all rasters and vectors in the **GRASS** cache that are not linked to a `GRaster` or `GVector`, use `mow("*")`.
#' * To remove all rasters or all vectors in the **GRASS** cache, use `mow("*", type = "rasters")` or `mow("*", type = "vectors")`.
#' * To remove all rasters or all vectors in the **GRASS** cache *except* for certain ones, use `mow("*", keep = list(GRaster_to_keep, GVector_to_keep))`. You can combine this with the `keep` argument to retain specific rasters or vectors. For example, you can use `mow("*", type = "rasters", keep = list(GRaster_to_keep))`.
#'
#' @param x Any of:
#' * `"unlinked"` (default): Delete **GRASS** rasters and/or vectors that are unlinked to `GRaster`s or `GVector`s in the environment in which the function was called, or the environment named in `pos`.
#' * A `GRaster` or `GVector`: Delete the **GRASS** raster or vector pointed to by this object.
#' * A `list` of `GRaster`s and/or `GVector`s: Delete the **GRASS** raster(s) and/or vector(s) pointed to by these objects.
#' * `"*"`: Delete *all* **GRASS** rasters and/or vectors pointed to by objects in the environment named in `pos`. Only objects in `keep` will not be deleted.
#'
#' @param pos Either `NULL` (default), or an environment. This is used only if `x` is `"unlinked"` or `"*"`. In that case, if `pos` is `NULL`, the environment in which this function was called will be searched for `GRaster`s and `GVector`s for removal of their associated **GRASS** rasters and vectors. Otherwise, the named environment will be searched.
#'
#' @param type Either `NULL` or a character vector. This is used only if `x` is `"unlinked"` or `"*"`. If `NULL`, all rasters and vectors in the **GRASS** cache are candidates for deletion. Otherwise, this can be either `"rasters"`, `"vectors"`, or both.
#'
#' @param keep Either `NULL` (default) or a `list()` of `GRaster`s and/or `GVector`s that you want to retain. This is used only if `x` is `"unlinked"` or `"*"`. The rasters and vectors in **GRASS** pointed to by these objects will not be deleted.
#'
#' @param verbose Logical: If `TRUE` (default), report progress.
#'
#' @param ask Logical: If `TRUE` (default), prompt for reassurance. This is used only if `x` is `"unlinked"` or `"*"`.
#'
#' @returns Invisibly returns a named vector with the number of rasters and vectors deleted.
#'
#' @seealso [terra::tmpFiles()]
#'
#' @example man/examples/ex_mow.r
#'
#' @aliases mow
#' @rdname mow
#' @export mow
mow <- function(
x = "unlinked",
pos = NULL,
type = NULL,
keep = NULL,
verbose = TRUE,
ask = TRUE
) {
### delete a single GRaster or GVector
######################################
if (inherits(x, "GRaster") | inherits(x, "GVector")) {
.locationRestore(x)
.rm(x)
return(invisible(c(rasters = 0, vectors = 0)))
}
### delete a list of GRasters/GVectors
######################################
if (is.list(x)) {
# make data table of objects
GSpatials <- data.table::data.table()
for (i in seq_along(x)) {
thisClass <- if (inherits(x[[i]], "GRaster")) {
"GRaster"
} else if (inherits(x[[i]], "GVector")) {
"GVector"
} else {
"other"
}
GSpatials <- rbind(
GSpatials,
data.table::data.table(
sources = sources(x[[i]]),
project = .location(x[[i]]),
class = thisClass
)
)
}
out <- c(rasters = 0L, vectors = 0L)
# delete rasters
if (any(GSpatials$class == "GRaster")) {
projs <- unique(GSpatials$project[GSpatials$class == "GRaster"])
if (verbose | faster("verbose")) omnibus::say("Deleting ", sum(GSpatials$class == "GRaster"), " raster(s) from the GRASS cache...")
for (proj in projs) {
.locationRestore(proj)
srcs <- GSpatials$sources[GSpatials$class == "GRaster" & GSpatials$project == proj]
out[["rasters"]] <- out[["rasters"]] + length(srcs)
.rm(srcs, type = "rasters", verify = FALSE)
}
}
# delete vectors
if (any(GSpatials$class == "GVector")) {
projs <- unique(GSpatials$project[GSpatials$class == "GVector"])
if (verbose | faster("verbose")) omnibus::say("Deleting ", sum(GSpatials$class == "GVector"), " vector(s) from the GRASS cache...")
for (proj in projs) {
.locationRestore(proj)
srcs <- GSpatials$sources[GSpatials$class == "GVector" & GSpatials$project == proj]
out[["vectors"]] <- out[["vectors"]] + length(srcs)
.rm(srcs, type = "vectors", verify = FALSE)
}
}
return(invisible(out))
}
### delete either everything except objects in `keep` or just unlinked rasters/vectors
######################################################################################
if (is.character(x)) {
x <- omnibus::pmatchSafe(x, c("*", "unlinked"), nmax = 1L)
if (is.null(type)) type <- c("rasters", "vectors")
type <- omnibus::pmatchSafe(type, c("rasters", "vectors"), nmax = 2L)
if (ask & x %in% c("*", "unlinked")) {
response <- readline("This action will break any existing GRasters and GVectors.\nAre you sure you want to empty the entire GRASS cache? (Y/n) ")
if (response != "Y") {
if (verbose | faster("verbose")) omnibus::say("Nothing deleted.")
return(invisible(c(rasters = 0, vectors = 0)))
}
}
if (x == "*" && !is.null(keep) && !is.list(keep)) stop("Argument `keep` must be a list or NULL.")
### get GRASS file names in each project/location
projs <- names(.fasterRaster$locations)
grassObjs <- list()
for (proj in projs) {
.locationRestore(proj)
grassObjs[[length(grassObjs) + 1L]] <- .ls(type = type)
names(grassObjs)[length(grassObjs)] <- proj
}
if (all(sapply(grassObjs, length) == 0L)) {
if (verbose | faster("verbose")) omnibus::say("Nothing deleted.")
return(invisible(c(rasters = 0, vectors = 0)))
}
### get just UNLINKED rasters/vectors
if (x == "unlinked") {
# get all R objects
if (is.null(pos)) {
rObjs <- ls(envir = parent.frame(n = 1L))
} else {
rObjs <- ls(pos)
}
# get sources of R objects
srcs <- character()
for (i in seq_along(rObjs)) {
thisObj <- get(rObjs[[i]])
if (inherits(thisObj, c("GRaster", "GVector"))) {
srcs <- c(srcs, sources(thisObj))
}
}
# remove linked ones
for (proj in projs) {
grassObjs[[proj]] <- grassObjs[[proj]][!(grassObjs[[proj]] %in% srcs)]
}
} else if (x == "*") {
# remove keep from list to be deleted
if (is.list(keep)) {
srcs <- character()
for (i in seq_along(keep)) srcs <- c(srcs, sources(keep[[i]]))
for (proj in projs) {
grassObjs[[proj]] <- grassObjs[[proj]][!(grassObjs[[proj]] %in% srcs)]
}
}
}
out <- c(rasters = 0, vectors = 0)
for (proj in projs) {
out[["rasters"]] <- out[["rasters"]] + sum(names(grassObjs[[proj]]) == "raster")
out[["vectors"]] <- out[["vectors"]] + sum(names(grassObjs[[proj]]) == "vector")
}
if (all(sapply(grassObjs, length) == 0)) {
if (verbose | faster("verbose")) omnibus::say("Nothing deleted.")
return(invisible(out))
} else {
if (verbose | faster("verbose")) omnibus::say("Deleting ", out[["rasters"]], " raster(s) and ", out[["vectors"]], " vector(s)...")
for (proj in projs) {
if (length(grassObjs[[proj]]) > 0L) {
if (any(names(grassObjs[[proj]]) == "raster")) {
.locationRestore(proj)
.rm(grassObjs[[proj]], type = "raster", warn = FALSE, verify = FALSE)
}
if (any(names(grassObjs[[proj]]) == "vector")) {
.locationRestore(proj)
.rm(grassObjs[[proj]], type = "vector", warn = FALSE, verify = FALSE)
}
}
}
}
invisible(return(invisible(out)))
}
} # EOF
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.