diff --git a/.Rbuildignore b/.Rbuildignore
index c1adbe6..6ef99de 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -7,3 +7,4 @@
^CRAN-RELEASE$
^CRAN-SUBMISSION$
^man/figures
+^\.github$
diff --git a/.github/.gitignore b/.github/.gitignore
new file mode 100644
index 0000000..2d19fc7
--- /dev/null
+++ b/.github/.gitignore
@@ -0,0 +1 @@
+*.html
diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml
new file mode 100644
index 0000000..a3ac618
--- /dev/null
+++ b/.github/workflows/R-CMD-check.yaml
@@ -0,0 +1,49 @@
+# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
+# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
+on:
+ push:
+ branches: [main, master]
+ pull_request:
+ branches: [main, master]
+
+name: R-CMD-check
+
+jobs:
+ R-CMD-check:
+ runs-on: ${{ matrix.config.os }}
+
+ name: ${{ matrix.config.os }} (${{ matrix.config.r }})
+
+ strategy:
+ fail-fast: false
+ matrix:
+ config:
+ - {os: macos-latest, r: 'release'}
+ - {os: windows-latest, r: 'release'}
+ - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'}
+ - {os: ubuntu-latest, r: 'release'}
+ - {os: ubuntu-latest, r: 'oldrel-1'}
+
+ env:
+ GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
+ R_KEEP_PKG_SOURCE: yes
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: r-lib/actions/setup-pandoc@v2
+
+ - uses: r-lib/actions/setup-r@v2
+ with:
+ r-version: ${{ matrix.config.r }}
+ http-user-agent: ${{ matrix.config.http-user-agent }}
+ use-public-rspm: true
+
+ - uses: r-lib/actions/setup-r-dependencies@v2
+ with:
+ extra-packages: any::rcmdcheck
+ needs: check
+
+ - uses: r-lib/actions/check-r-package@v2
+ with:
+ upload-snapshots: true
diff --git a/DESCRIPTION b/DESCRIPTION
index acb5382..2d17419 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,8 +1,8 @@
Package: envi
Type: Package
Title: Environmental Interpolation using Spatial Kernel Density Estimation
-Version: 0.1.15
-Date: 2022-08-30
+Version: 0.1.16.9000
+Date: 2022-12-16
Authors@R:
c(person(given = "Ian D.",
family = "Buller",
@@ -28,7 +28,7 @@ Description: Estimates an ecological niche using occurrence data, covariates, an
License: Apache License (>= 2.0)
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
-RoxygenNote: 7.2.1
+RoxygenNote: 7.2.2
Depends:
R (>= 3.5.0)
Imports:
@@ -43,15 +43,13 @@ Imports:
grDevices,
iterators,
pls,
- raster,
- rgeos,
ROCR,
- sp,
+ sf,
sparr,
spatstat.geom,
- stats
+ stats,
+ terra
Suggests:
- maptools,
R.rsp,
RStoolbox,
spatstat.data,
diff --git a/NAMESPACE b/NAMESPACE
index a1e529b..2303b28 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -34,23 +34,10 @@ importFrom(graphics,plot.new)
importFrom(graphics,title)
importFrom(iterators,icount)
importFrom(pls,cvsegments)
-importFrom(raster,crs)
-importFrom(raster,cut)
-importFrom(raster,extract)
-importFrom(raster,image)
-importFrom(raster,projectRaster)
-importFrom(raster,raster)
-importFrom(raster,rasterToPoints)
-importFrom(raster,reclassify)
-importFrom(raster,values)
-importFrom(rgeos,gBuffer)
-importFrom(sp,CRS)
-importFrom(sp,Polygon)
-importFrom(sp,Polygons)
-importFrom(sp,SpatialPolygons)
-importFrom(sp,bbox)
-importFrom(sp,coordinates)
-importFrom(sp,gridded)
+importFrom(sf,st_bbox)
+importFrom(sf,st_buffer)
+importFrom(sf,st_coordinates)
+importFrom(sf,st_polygon)
importFrom(sparr,risk)
importFrom(spatstat.geom,as.solist)
importFrom(spatstat.geom,im.apply)
@@ -65,3 +52,12 @@ importFrom(spatstat.geom,superimpose)
importFrom(stats,median)
importFrom(stats,na.omit)
importFrom(stats,sd)
+importFrom(terra,classify)
+importFrom(terra,crds)
+importFrom(terra,crs)
+importFrom(terra,extract)
+importFrom(terra,image)
+importFrom(terra,project)
+importFrom(terra,rast)
+importFrom(terra,res)
+importFrom(terra,values)
diff --git a/NEWS.md b/NEWS.md
index b202def..c10e582 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,5 +1,14 @@
# envi (development version)
+# envi v0.1.16.9000
+* Migrated R-spatial dependencies
+* Replaced `raster`, `rgeos`, and `sp` packages in Imports with `terra` and `sf` because of imminent package retirements
+* Removed `maptools` from Suggests (replaced with new internal function `as.im.SpatRaster()`)
+* Thank you, [Roger Bivand](https://github.com/rsbivand), for the notice. Relates to [ndi Issue #3](https://github.com/lance-waller-lab/envi/issues/3)
+* Note: `raster` is a dependency of `RStoolbox` (at present) which is used in the vignette
+* Updated test, examples, vignette, and documentation throughout
+* Added GitHub R-CMD-check
+
# envi v0.1.15
* Uwe Ligges suggested (2022-08-26) that some parallel cluster is not cleanly closed in the tests
* Added `future::plan(future::multisession)` in tests to remove the files in temp directory
diff --git a/R/div_plot.R b/R/div_plot.R
index 80d0e99..971be00 100644
--- a/R/div_plot.R
+++ b/R/div_plot.R
@@ -1,8 +1,8 @@
-#' Prepare an 'im' or 'raster' object for plotting with diverging color palette
+#' Prepare an 'im' or 'SpatRaster' object for plotting with diverging color palette
#'
-#' Internal function to convert 'im' object or 'RasterLayer' object to values readable by \code{\link[fields]{image.plot}} function within the \code{\link{plot_obs}}, \code{\link{plot_predict}}, and \code{\link{plot_perturb}} functions.
+#' Internal function to convert 'im' object or 'SpatRaster' object to values readable by \code{\link[fields]{image.plot}} function within the \code{\link{plot_obs}}, \code{\link{plot_predict}}, and \code{\link{plot_perturb}} functions.
#'
-#' @param input An object of class 'im' or 'RasterLayer' from the \code{\link{lrren}} function.
+#' @param input An object of class 'im' or 'SpatRaster' from the \code{\link{lrren}} function.
#' @param plot_cols Character string of length three (3) specifying the colors for plotting: 1) presence, 2) neither, and 3) absence from the \code{\link{plot_obs}} function.
#' @param midpoint Numeric. The value to center the diverging color palette.
#' @param thresh_up Numeric. The upper value to concatenate the color key. The default (NULL) uses the maximum value from \code{input}.
@@ -20,7 +20,7 @@
#' }
#'
#' @importFrom grDevices colorRampPalette
-#' @importFrom raster raster
+#' @importFrom terra rast
#'
#' @keywords internal
@@ -33,15 +33,15 @@ div_plot <- function(input,
# Inputs
if (inherits(input, "im")) {
- out <- raster::raster(input)
+ out <- terra::rast(input)
} else { out <- input }
if (length(cols) != 3) {
stop("The 'cols' argument must be a vector of length 3")
}
- min_raw_value <- min(out[is.finite(out)], na.rm = TRUE) # minimum absolute value of raster
- max_raw_value <- max(out[is.finite(out)], na.rm = TRUE) # maximum absolute value of raster
+ min_raw_value <- min(out[is.finite(out)], na.rm = TRUE) # minimum absolute value of SpatRaster
+ max_raw_value <- max(out[is.finite(out)], na.rm = TRUE) # maximum absolute value of SpatRaster
# Restrict spurious log relative risk values
if (!is.null(thresh_low)) {
@@ -60,8 +60,8 @@ div_plot <- function(input,
# Identify ramp above and below midpoint
lowerhalf <- length(out[out < midpoint & !is.na(out)]) # values below 0
upperhalf <- length(out[out > midpoint & !is.na(out)]) # values above 0
- min_absolute_value <- min(out[is.finite(out)], na.rm = TRUE) # minimum absolute value of raster
- max_absolute_value <- max(out[is.finite(out)], na.rm = TRUE) # maximum absolute value of raster
+ min_absolute_value <- min(out[is.finite(out)], na.rm = TRUE) # minimum absolute value of SpatRaster
+ max_absolute_value <- max(out[is.finite(out)], na.rm = TRUE) # maximum absolute value of SpatRaster
# Color ramp parameters
## Colors
diff --git a/R/lrren.R b/R/lrren.R
index 14c9c36..a84cfcf 100644
--- a/R/lrren.R
+++ b/R/lrren.R
@@ -70,12 +70,11 @@
#' @importFrom grDevices chull
#' @importFrom iterators icount
#' @importFrom pls cvsegments
-#' @importFrom raster extract raster
-#' @importFrom rgeos gBuffer
-#' @importFrom sp bbox coordinates Polygon Polygons SpatialPolygons
+#' @importFrom sf st_bbox st_buffer st_coordinates st_polygon
#' @importFrom sparr risk
#' @importFrom spatstat.geom owin ppp
#' @importFrom stats na.omit
+#' @importFrom terra extract rast values
#' @export
#'
#' @examples
@@ -89,8 +88,8 @@
#' grad <- spatstat.data::bei.extra[[2]]
#' elev$v <- scale(elev)
#' grad$v <- scale(grad)
-#' elev_raster <- raster::raster(elev)
-#' grad_raster <- raster::raster(grad)
+#' elev_raster <- terra::rast(elev)
+#' grad_raster <- terra::rast(grad)
#'
#' # Presence data
#' presence <- spatstat.data::bei
@@ -115,8 +114,10 @@
#' obs_locs <- obs_locs[ , c(6, 2, 3, 1, 4, 5)]
#'
#' # Prediction Data
-#' predict_locs <- data.frame(raster::rasterToPoints(elev_raster))
-#' predict_locs$layer2 <- raster::extract(grad_raster, predict_locs[, 1:2])
+#' predict_xy <- terra::crds(elev_raster)
+#' predict_locs <- as.data.frame(predict_xy)
+#' predict_locs$elev <- terra::extract(elev_raster, predict_xy)[ , 1]
+#' predict_locs$grad <- terra::extract(grad_raster, predict_xy)[ , 1]
#'
#' # Run lrren
#' test_lrren <- lrren(obs_locs = obs_locs,
@@ -138,7 +139,7 @@ lrren <- function(obs_locs,
n_core = 2,
poly_buffer = NULL,
obs_window = NULL,
- verbose = FALSE,
+ verbose = FALSE,
...) {
if (verbose == TRUE) { message("Estimating relative risk surfaces\n") }
@@ -148,17 +149,15 @@ lrren <- function(obs_locs,
# Compute spatial windows
## Calculate inner boundary polygon (extent of presence and absence locations in environmental space)
inner_chull <- concaveman::concaveman(as.matrix(obs_locs[ , 5:6]))
- inner_chull_pts <- sp::coordinates(inner_chull)
- inner_chull_pts <- rbind(inner_chull_pts, inner_chull_pts[1, ])
- inner_chull_poly <- sp::SpatialPolygons(list(sp::Polygons(list(sp::Polygon(inner_chull_pts)), 1)))
-
+ inner_chull_poly <- sf::st_polygon(list(inner_chull))
+
if (is.null(poly_buffer)) {
- poly_buffer <- abs(min(diff(sp::bbox(inner_chull_poly)[1, ]), diff(sp::bbox(inner_chull_poly)[2, ])) / 100)
+ poly_buffer <- abs(min(diff(sf::st_bbox(inner_chull_poly)[c(1,3)]), diff(sf::st_bbox(inner_chull_poly)[c(2,4)])) / 100)
}
# add small buffer around polygon to include boundary points
- inner_chull_poly_buffer <- rgeos::gBuffer(inner_chull_poly, width = poly_buffer, byid = TRUE)
- inner_poly <- inner_chull_poly_buffer@polygons[[1]]@Polygons[[1]]@coords
+ inner_chull_poly_buffer <- sf::st_buffer(inner_chull_poly, dist = poly_buffer, byid = TRUE)
+ inner_poly <- sf::st_polygon(list(as.matrix(inner_chull_poly_buffer)))
if (is.null(predict_locs)) {
outer_chull_poly <- inner_chull_poly_buffer
@@ -166,17 +165,16 @@ lrren <- function(obs_locs,
} else {
## Calculate outer boundary polygon (full extent of geographical extent in environmental space)
if (nrow(predict_locs) > 5000000) { # convex hull
- outer_chull <- grDevices::chull(x = stats::na.omit(predict_locs)[ , 3], y = stats::na.omit(predict_locs)[ , 4])
- outer_chull_pts <- predict_locs[c(outer_chull, outer_chull[1]), 3:4]
+ predict_locs_woNAs <- stats::na.omit(predict_locs)
+ outer_chull <- grDevices::chull(x = predict_locs_woNAs[ , 3], y = predict_locs_woNAs[ , 4])
+ outer_chull_pts <- predict_locs_woNAs[c(outer_chull, outer_chull[1]), 3:4]
} else { # concave hull
- outer_chull <- concaveman::concaveman(as.matrix(stats::na.omit(predict_locs)[ , 3:4]))
- outer_chull_pts <- sp::coordinates(outer_chull)
+ outer_chull_pts <- concaveman::concaveman(as.matrix(stats::na.omit(predict_locs[ , 3:4])))
}
- outer_chull_pts <- rbind(outer_chull_pts, outer_chull_pts[1, ])
- outer_chull_poly <- sp::SpatialPolygons(list(sp::Polygons(list(sp::Polygon(outer_chull_pts)), 1)))
- #add small buffer around polygon to include boundary points
- outer_chull_poly_buffer <- rgeos::gBuffer(outer_chull_poly, width = poly_buffer, byid = TRUE)
- outer_poly <- outer_chull_poly_buffer@polygons[[1]]@Polygons[[1]]@coords #extract coordinates of new polygon
+ outer_chull_poly <- sf::st_polygon(list(as.matrix(outer_chull_pts)))
+ # add small buffer around polygon to include boundary points
+ outer_chull_poly_buffer <- sf::st_buffer(outer_chull_poly, dist = poly_buffer, byid = TRUE)
+ outer_poly <- sf::st_polygon(list(as.matrix(outer_chull_poly_buffer)))
}
if (conserve == FALSE & is.null(predict_locs)) {
@@ -185,8 +183,8 @@ lrren <- function(obs_locs,
if (conserve == TRUE) { window_poly <- inner_poly } else { window_poly <- outer_poly }
if (is.null(obs_window)) {
- wind <- spatstat.geom::owin(poly = list(x = rev(window_poly[ , 1]),
- y = rev(window_poly[ , 2])))
+ wind <- spatstat.geom::owin(poly = list(x = rev(sf::st_coordinates(window_poly)[ , 1]),
+ y = rev(sf::st_coordinates(window_poly)[ , 2])))
} else { wind <- obs_window }
# Input Preparation
@@ -207,7 +205,7 @@ lrren <- function(obs_locs,
obs <- sparr::risk(f = ppp_presence,
g = ppp_absence,
tolerate = TRUE,
- verbose = verbose,
+ verbose = verbose,
...)
bandw <- obs$f$h0
@@ -228,17 +226,17 @@ lrren <- function(obs_locs,
# Project relative risk surface into geographic space
if (verbose == TRUE) { message("Predicting area of interest") }
- # Convert to semi-continuous raster
- rr_raster <- raster::raster(obs$rr)
+ # Convert to semi-continuous SpatRaster
+ rr_raster <- terra::rast(obs$rr)
- # Convert to categorical raster
- pval_raster <- raster::raster(obs$P)
+ # Convert to categorical SpatRaster
+ pval_raster <- terra::rast(obs$P)
# Prediction locations
extract_points <- cbind(predict_locs[ , 3], predict_locs[ , 4])
extract_predict <- data.frame("predict_locs" = predict_locs,
- "rr" = raster::extract(rr_raster, extract_points),
- "pval" = raster::extract(pval_raster, extract_points))
+ "rr" = terra::extract(rr_raster, extract_points)[ , 1],
+ "pval" = terra::extract(pval_raster, extract_points)[ , 1])
output <- list("obs" = obs,
"presence" = ppp_presence,
@@ -326,19 +324,19 @@ lrren <- function(obs_locs,
rand_lrr <- sparr::risk(f = ppp_presence_training,
g = ppp_absence_training,
tolerate = TRUE,
- verbose = FALSE,
+ verbose = FALSE,
...)
- ##### Convert to semi-continuous raster
- rr_raster <- raster::raster(rand_lrr$rr)
- rr_raster[is.na(rr_raster[])] <- 0 # if NA, assigned null value (log(rr) = 0)
+ ##### Convert to semi-continuous SpatRaster
+ rr_raster <- terra::rast(rand_lrr$rr)
+ rr_raster[is.na(terra::values(rr_raster))] <- 0 # if NA, assigned null value (log(rr) = 0)
##### Predict testing dataset
extract_testing <- testing[ , 5:6]
##### Output for each k-fold
###### Record category (semi-continuous) of testing data
- cv_predictions_rr <- raster::extract(rr_raster, extract_testing)
+ cv_predictions_rr <- terra::extract(rr_raster, extract_testing)[ , 2]
cv_labels <- testing[ , 4] # Record labels (marks) of testing data
par_results <- list("cv_predictions_rr" = cv_predictions_rr,
diff --git a/R/package.R b/R/package.R
index 328eff2..20f8b63 100644
--- a/R/package.R
+++ b/R/package.R
@@ -30,7 +30,7 @@
#' @aliases envi-package envi
#' @docType package
#'
-#' @section Dependencies: The 'envi' package relies heavily upon \code{\link{sparr}}, \code{\link{spatstat.geom}}, and \code{\link{raster}}. For a single species (presence/absence data), the spatial relative risk function uses the \code{\link[sparr]{risk}} function. Cross-validation is can be performed in parallel using the \code{\link{future}}, \code{\link{doFuture}}, \code{\link{doRNG}}, and \code{\link{foreach}} packages. Spatial perturbation is performed using the \code{\link[spatstat.geom]{rjitter}} function. Basic visualizations rely on the \code{\link[spatstat.geom]{plot.ppp}} and \code{\link[fields]{image.plot}} functions.
+#' @section Dependencies: The 'envi' package relies heavily upon \code{\link{sparr}}, \code{\link{spatstat.geom}}, \code{\link{sf}}, and \code{\link{terra}}. For a single species (presence/absence data), the spatial relative risk function uses the \code{\link[sparr]{risk}} function. Cross-validation is can be performed in parallel using the \code{\link{future}}, \code{\link{doFuture}}, \code{\link{doRNG}}, and \code{\link{foreach}} packages. Spatial perturbation is performed using the \code{\link[spatstat.geom]{rjitter}} function. Basic visualizations rely on the \code{\link[spatstat.geom]{plot.ppp}} and \code{\link[fields]{image.plot}} functions.
#'
#' @author Ian D. Buller\cr \emph{Environmental Health Sciences, Emory University, Atlanta, Georgia, USA.}\cr
#'
@@ -50,10 +50,9 @@ NULL
#' @importFrom grDevices chull colorRampPalette
#' @importFrom iterators icount
#' @importFrom pls cvsegments
-#' @importFrom raster crs cut extract image projectRaster raster rasterToPoints reclassify values
-#' @importFrom rgeos gBuffer
#' @importFrom ROCR performance prediction
-#' @importFrom sp bbox coordinates CRS gridded Polygon Polygons SpatialPolygons
+#' @importFrom sf st_bbox st_buffer st_coordinates st_polygon
#' @importFrom spatstat.geom as.solist im.apply marks owin pixellate plot.ppp ppp rjitter setmarks superimpose
#' @importFrom stats median na.omit sd
+#' @importFrom terra crds crs image project rast res classify values
NULL
diff --git a/R/perlrren.R b/R/perlrren.R
index 4ccfc67..8de29ab 100644
--- a/R/perlrren.R
+++ b/R/perlrren.R
@@ -58,9 +58,9 @@
#' @importFrom foreach %do% %dopar% foreach setDoPar
#' @importFrom future multisession plan
#' @importFrom iterators icount
-#' @importFrom raster crs
#' @importFrom spatstat.geom as.solist im.apply marks owin ppp rjitter superimpose
#' @importFrom stats median sd
+#' @importFrom terra crs
#' @export
#'
#' @examples
@@ -115,10 +115,6 @@ perlrren <- function(obs_ppp,
verbose = FALSE,
...) {
- if (!identical(raster::crs(obs_ppp), raster::crs(covariates))) {
- stop("The arguments 'obs_ppp' and 'covariates' must have the same coordinate reference system")
- }
-
if (is.null(radii)) {
radii <- rep(0, nlevels(spatstat.geom::marks(obs_ppp)[ , 5]))
message("The argument 'radii' is unspecified and the observation coordinates are not perturbed")
@@ -143,7 +139,7 @@ perlrren <- function(obs_ppp,
### Set function used in foreach
if (parallel == TRUE) {
oldplan <- doFuture::registerDoFuture()
- on.exit(with(oldplan, foreach::setDoPar(fun=fun, data=data, info=info)), add = TRUE)
+ on.exit(with(oldplan, foreach::setDoPar(fun = fun, data = data, info = info)), add = TRUE)
future::plan(future::multisession, workers = n_core)
`%fun%` <- doRNG::`%dorng%`
} else { `%fun%` <- foreach::`%do%` }
@@ -246,8 +242,8 @@ perlrren <- function(obs_ppp,
# Project relative risk surface into geographic space
if (verbose == TRUE) { message("\nPredicting area of interest") }
window_poly <- out_par[[3]][[1]]
- wind <- spatstat.geom::owin(poly = list(x = rev(window_poly[ , 1]),
- y = rev(window_poly[ , 2])))
+ wind <- spatstat.geom::owin(poly = list(x = rev(sf::st_coordinates(window_poly)[ , 1]),
+ y = rev(sf::st_coordinates(window_poly)[ , 2])))
xxxxx <- spatstat.geom::ppp(x = predict_locs[ , 3],
y = predict_locs[ , 4],
diff --git a/R/plot_cv.R b/R/plot_cv.R
index e841bef..eae6e01 100644
--- a/R/plot_cv.R
+++ b/R/plot_cv.R
@@ -24,8 +24,8 @@
#' grad <- spatstat.data::bei.extra[[2]]
#' elev$v <- scale(elev)
#' grad$v <- scale(grad)
-#' elev_raster <- raster::raster(elev)
-#' grad_raster <- raster::raster(grad)
+#' elev_raster <- terra::rast(elev)
+#' grad_raster <- terra::rast(grad)
#'
#' # Presence data
#' presence <- spatstat.data::bei
@@ -49,14 +49,8 @@
#' obs_locs$id <- seq(1, nrow(obs_locs), 1)
#' obs_locs <- obs_locs[ , c(6, 2, 3, 1, 4, 5)]
#'
-#' # Prediction Data
-#' predict_locs <- data.frame(raster::rasterToPoints(elev_raster))
-#' predict_locs$layer2 <- raster::extract(grad_raster, predict_locs[, 1:2])
-#'
#' # Run lrren
#' test_lrren <- lrren(obs_locs = obs_locs,
-#' predict_locs = predict_locs,
-#' predict = TRUE,
#' cv = TRUE)
#'
#' # Run plot_cv
diff --git a/R/plot_obs.R b/R/plot_obs.R
index aefb5ca..e3b1742 100644
--- a/R/plot_obs.R
+++ b/R/plot_obs.R
@@ -14,8 +14,8 @@
#'
#' @importFrom fields image.plot
#' @importFrom graphics par
-#' @importFrom raster cut raster values
#' @importFrom spatstat.geom plot.ppp setmarks superimpose
+#' @importFrom terra rast values
#' @export
#'
#' @examples
@@ -29,8 +29,8 @@
#' grad <- spatstat.data::bei.extra[[2]]
#' elev$v <- scale(elev)
#' grad$v <- scale(grad)
-#' elev_raster <- raster::raster(elev)
-#' grad_raster <- raster::raster(grad)
+#' elev_raster <- terra::rast(elev)
+#' grad_raster <- terra::rast(grad)
#'
#' # Presence data
#' presence <- spatstat.data::bei
@@ -54,15 +54,9 @@
#' obs_locs$id <- seq(1, nrow(obs_locs), 1)
#' obs_locs <- obs_locs[ , c(6, 2, 3, 1, 4, 5)]
#'
-#' # Prediction Data
-#' predict_locs <- data.frame(raster::rasterToPoints(elev_raster))
-#' predict_locs$layer2 <- raster::extract(grad_raster, predict_locs[, 1:2])
-#'
#' # Run lrren
#' test_lrren <- lrren(obs_locs = obs_locs,
-#' predict_locs = predict_locs,
-#' predict = TRUE,
-#' cv = TRUE)
+#' cv = FALSE)
#'
#' # Run plot_obs
#' plot_obs(input = test_lrren)
@@ -136,12 +130,12 @@ plot_obs <- function(input,
cex.axis = 0.67))
# Plot 3: Significant p-values
- pvalp <- raster::raster(input$out$obs$P) # create raster
- pvalp <- raster::cut(pvalp,
- breaks = c(-Inf, alpha / 2, 1 - alpha / 2, Inf),
- right = FALSE)
+ pvalp <- terra::rast(input$out$obs$P) # create raster
+ terra::values(pvalp) <- cut(terra::values(pvalp),
+ breaks = c(-Inf, alpha / 2, 1 - alpha / 2, Inf),
+ right = FALSE)
- if (all(raster::values(pvalp)[!is.na(raster::values(pvalp))] == 2)) {
+ if (all(terra::values(pvalp)[!is.na(terra::values(pvalp))] == 2)) {
pcols <- plot_cols[2]
brp <- c(1, 3)
atp <- 2
diff --git a/R/plot_perturb.R b/R/plot_perturb.R
index afcad85..b90fc08 100644
--- a/R/plot_perturb.R
+++ b/R/plot_perturb.R
@@ -19,9 +19,8 @@
#'
#' @importFrom fields image.plot
#' @importFrom graphics par
-#' @importFrom raster crs raster projectRaster
-#' @importFrom sp CRS
#' @importFrom spatstat.geom pixellate
+#' @importFrom terra crs project rast
#'
#' @export
#'
@@ -179,41 +178,45 @@ plot_perturb <- function(input,
if (predict == TRUE) {
- # Convert 'im' objects to spatially projected 'RasterLayer' objects
+ # Convert 'im' objects to spatially projected 'SpatRaster' objects
lrr_mean <- spatstat.geom::pixellate(input$predict,
weights = marks(input$predict)$lrr_mean)
- lrr_mean <- raster::raster(lrr_mean)
- raster::crs(lrr_mean) <- sp::CRS(SRS_string = cref0)
+ lrr_mean <- terra::rast(lrr_mean)
+ terra::crs(lrr_mean) <- cref0
if (!is.null(cref1)) {
- lrr_mean <- raster::projectRaster(lrr_mean,
- crs = sp::CRS(SRS_string = cref1))
+ lrr_mean <- terra::project(lrr_mean,
+ y = cref1,
+ method = "bilinear")
}
lrr_sd <- spatstat.geom::pixellate(input$predict,
weights = marks(input$predict)$lrr_sd)
- lrr_sd <- raster::raster(lrr_sd)
- raster::crs(lrr_sd) <- sp::CRS(SRS_string = cref0)
+ lrr_sd <- terra::rast(lrr_sd)
+ terra::crs(lrr_sd) <- cref0
if (!is.null(cref1)) {
- lrr_sd <- raster::projectRaster(lrr_sd,
- crs = sp::CRS(SRS_string = cref1))
+ lrr_sd <- terra::project(lrr_sd,
+ y = cref1,
+ method = "bilinear")
}
pval_mean <- spatstat.geom::pixellate(input$predict,
weights = marks(input$predict)$pval_mean)
- pval_mean <- raster::raster(pval_mean)
- raster::crs(pval_mean) <- sp::CRS(SRS_string = cref0)
+ pval_mean <- terra::rast(pval_mean)
+ terra::crs(pval_mean) <- cref0
if (!is.null(cref1)) {
- pval_mean <- raster::projectRaster(pval_mean,
- crs = sp::CRS(SRS_string = cref1))
+ pval_mean <- terra::project(pval_mean,
+ y = cref1,
+ method = "bilinear")
}
pval_prop <- spatstat.geom::pixellate(input$predict,
weights = marks(input$predict)$pval_prop)
- pval_prop <- raster::raster(pval_prop)
- raster::crs(pval_prop) <- sp::CRS(SRS_string = cref0)
+ pval_prop <- terra::rast(pval_prop)
+ terra::crs(pval_prop) <- cref0
if (!is.null(cref1)) {
- pval_prop <- raster::projectRaster(pval_prop,
- crs = sp::CRS(SRS_string = cref1))
+ pval_prop <- terra::project(pval_prop,
+ y = cref1,
+ method = "bilinear")
}
# Plot 5: mean log relative risk
diff --git a/R/plot_predict.R b/R/plot_predict.R
index e2ffa61..d9caa26 100644
--- a/R/plot_predict.R
+++ b/R/plot_predict.R
@@ -16,8 +16,7 @@
#'
#' @importFrom fields image.plot
#' @importFrom graphics par
-#' @importFrom raster crs cut image projectRaster raster reclassify values
-#' @importFrom sp coordinates CRS gridded
+#' @importFrom terra crs image project rast classify values
#' @export
#'
#' @examples
@@ -31,8 +30,8 @@
#' grad <- spatstat.data::bei.extra[[2]]
#' elev$v <- scale(elev)
#' grad$v <- scale(grad)
-#' elev_raster <- raster::raster(elev)
-#' grad_raster <- raster::raster(grad)
+#' elev_raster <- terra::rast(elev)
+#' grad_raster <- terra::rast(grad)
#'
#' # Presence data
#' presence <- spatstat.data::bei
@@ -57,14 +56,15 @@
#' obs_locs <- obs_locs[ , c(6, 2, 3, 1, 4, 5)]
#'
#' # Prediction Data
-#' predict_locs <- data.frame(raster::rasterToPoints(elev_raster))
-#' predict_locs$layer2 <- raster::extract(grad_raster, predict_locs[, 1:2])
+#' predict_xy <- terra::crds(elev_raster)
+#' predict_locs <- as.data.frame(predict_xy)
+#' predict_locs$elev <- terra::extract(elev_raster, predict_xy)[ , 1]
+#' predict_locs$grad <- terra::extract(grad_raster, predict_xy)[ , 1]
#'
#' # Run lrren
#' test_lrren <- lrren(obs_locs = obs_locs,
#' predict_locs = predict_locs,
-#' predict = TRUE,
-#' cv = TRUE)
+#' predict = TRUE)
#'
#' # Run plot_predict
#' plot_predict(input = test_lrren, cref0 = "EPSG:5472")
@@ -90,59 +90,50 @@ plot_predict <- function(input,
op <- graphics::par(no.readonly = TRUE)
on.exit(graphics::par(op))
+
# Convert to geospatial rasters
- predict_risk <- data.frame("x" = input$out$predict$predict_locs.x,
- "y" = input$out$predict$predict_locs.y,
- "v" = input$out$predict$rr)
- naband <- predict_risk # save for next step
- sp::coordinates(predict_risk) <- ~ x + y # coordinates
- sp::gridded(predict_risk) <- TRUE # gridded
- predict_risk_raster <- raster::raster(predict_risk)
- raster::crs(predict_risk_raster) <- sp::CRS(SRS_string = cref0)
+ ## log relative risk
+ predict_risk <- data.frame("x" = input$out$predict[ , 1],
+ "y" = input$out$predict[ , 2],
+ "v" = input$out$predict$rr)
+ predict_risk_raster <- terra::rast(predict_risk)
+ terra::crs(predict_risk_raster) <- cref0
if (!is.null(cref1)) {
- predict_risk_raster <- raster::projectRaster(predict_risk_raster,
- crs = sp::CRS(SRS_string = cref1),
- method = "ngb",
- legacy = TRUE)
+ predict_risk_raster <- terra::project(predict_risk_raster,
+ y = cref1,
+ method = "bilinear")
+
}
-
- # Create separate layer for NAs (if any)
- naband$v <- ifelse(is.na(naband$v), 9999, naband$v)
- sp::coordinates(naband) <- ~ x + y # coordinates
- sp::gridded(naband) <- TRUE # gridded
- NA_risk_raster <- raster::raster(naband)
- raster::crs(NA_risk_raster) <- sp::CRS(SRS_string = cref0)
+
+ ## p-value
+ predict_tol <- data.frame("x" = input$out$predict[ , 1],
+ "y" = input$out$predict[ , 2],
+ "v" = input$out$predict$pval)
+ predict_tol_raster <- terra::rast(predict_tol)
+ terra::crs(predict_tol_raster) <- cref0
if (!is.null(cref1)) {
- NA_risk_raster <- raster::projectRaster(NA_risk_raster,
- crs = sp::CRS(SRS_string = cref1),
- method = "ngb",
- legacy = TRUE)
+ predict_tol_raster <- terra::project(predict_tol_raster,
+ y = cref1,
+ method = "bilinear")
}
- naband_reclass <- raster::reclassify(NA_risk_raster,
- c(-Inf, 9998, NA,
- 9998, Inf, 1))
- if (all(is.na(raster::values(naband_reclass)))) { naband_reclass <- NULL }
+ terra::values(predict_tol_raster) <- cut(terra::values(predict_tol_raster),
+ breaks = c(-Inf, alpha / 2, 1 - alpha / 2, Inf),
+ right = FALSE)
- # Convert to geospatial raster
- predict_tol <- data.frame("x" = input$out$predict$predict_locs.x,
- "y" = input$out$predict$predict_locs.y,
- "v" = input$out$predict$pval)
- sp::coordinates(predict_tol) <- ~ x + y # coordinates
- sp::gridded(predict_tol) <- TRUE # gridded
- predict_tol_raster <- raster::raster(predict_tol)
- raster::crs(predict_tol_raster) <- sp::CRS(SRS_string = cref0)
+ ## Separate layer for NAs (if any)
+ naband <- predict_risk
+ naband$v <- ifelse(is.na(naband$v), 9999, NA)
+ naband_raster <- terra::rast(naband)
+ terra::crs(naband_raster) <- cref0
if (!is.null(cref1)) {
- predict_tol_raster <- raster::projectRaster(predict_tol_raster,
- crs = sp::CRS(SRS_string = cref1),
- method = "ngb",
- legacy = TRUE)
+ naband_raster <- terra::project(naband_raster,
+ y = cref1,
+ method = "near")
}
-
- reclass_tol <- raster::cut(predict_tol_raster,
- breaks = c(-Inf, alpha / 2, 1 - alpha / 2, Inf),
- right = FALSE)
-
+
+ if (all(is.na(terra::values(naband_raster)))) { naband_raster <- NULL }
+
# Plot 1: log relative risk
rrp <- div_plot(input = predict_risk_raster,
cols = plot_cols[1:3],
@@ -164,12 +155,12 @@ plot_predict <- function(input,
las = 0,
labels = rrp$labels,
cex.axis = 0.67))
- if (!is.null(naband_reclass)) {
- raster::image(naband_reclass, col = plot_cols[4], add = TRUE)
+ if (!is.null(naband_raster)) {
+ terra::image(naband_raster, y = 1, col = plot_cols[4], add = TRUE)
}
# Plot 2: Significant p-values
- if (all(raster::values(reclass_tol)[!is.na(raster::values(reclass_tol))] == 2)) {
+ if (all(terra::values(predict_tol_raster)[!is.na(terra::values(predict_tol_raster))] == 2)) {
pcols <- plot_cols[2]
brp <- c(1, 3)
atp <- 2
@@ -181,7 +172,7 @@ plot_predict <- function(input,
labp <- c("presence", "insignificant", "absence")
}
- p2 <- fields::image.plot(reclass_tol,
+ p2 <- fields::image.plot(predict_tol_raster,
breaks = brp,
col = pcols,
axes = TRUE,
@@ -193,7 +184,7 @@ plot_predict <- function(input,
labels = labp,
las = 0,
cex.axis = 0.67))
- if (!is.null(naband_reclass)) {
- raster::image(naband_reclass, col = plot_cols[4], add = TRUE)
+ if (!is.null(naband_raster)) {
+ terra::image(naband_raster, y = 1, col = plot_cols[4], add = TRUE)
}
}
diff --git a/R/seq_plot.R b/R/seq_plot.R
index 0ef2be9..da739dc 100644
--- a/R/seq_plot.R
+++ b/R/seq_plot.R
@@ -1,8 +1,8 @@
-#' Prepare an 'im' or 'raster' object for plotting with sequential color palette
+#' Prepare an 'im' or 'SpatRaster' object for plotting with sequential color palette
#'
-#' Internal function to convert 'im' object or 'RasterLayer' object to values readable by \code{\link[fields]{image.plot}} function within the \code{\link{plot_perturb}} function.
+#' Internal function to convert 'im' object or 'SpatRaster' object to values readable by \code{\link[fields]{image.plot}} function within the \code{\link{plot_perturb}} function.
#'
-#' @param input An object of class 'im' or 'RasterLayer' from the \code{\link{perlrren}} function.
+#' @param input An object of class 'im' or 'SpatRaster' from the \code{\link{perlrren}} function.
#' @param plot_cols Character string of length three (3) specifying the colors for plotting: 1) presence, 2) neither, and 3) absence from the \code{\link{plot_obs}} function.
#' @param thresh_up Numeric. The upper value to concatenate the color key. The default (NULL) uses the maximum value from \code{input}.
#' @param digits Integer. The number of significant digits for the labels using the \code{\link[base]{round}} function (default is 1).
@@ -18,6 +18,7 @@
#' }
#'
#' @importFrom grDevices colorRampPalette
+#' @importFrom terra rast
#'
#' @keywords internal
#'
@@ -28,10 +29,10 @@ seq_plot <- function(input,
# Inputs
if (inherits(input, "im")) {
- out <- raster::raster(input)
+ out <- terra::rast(input)
} else { out <- input }
- max_raw_value <- max(out[is.finite(out)], na.rm = TRUE) # maximum absolute value of raster
+ max_raw_value <- max(out[is.finite(out)], na.rm = TRUE) # maximum absolute value of SpatRaster
# Restrict spurious standard deviation values
if (!is.null(thresh_up)) {
@@ -41,7 +42,7 @@ seq_plot <- function(input,
out[out >= thresh_up] <- thresh_up
}
- max_absolute_value <- max(out[is.finite(out)], na.rm = TRUE) # maximum absolute value of raster
+ max_absolute_value <- max(out[is.finite(out)], na.rm = TRUE) # maximum absolute value of SpatRaster
ncols <- length(out[!is.na(out)]) # number of values
## Colors
diff --git a/R/utils.R b/R/utils.R
index 3b10d06..ecf5807 100644
--- a/R/utils.R
+++ b/R/utils.R
@@ -32,3 +32,52 @@ progBar <- function(kk, N, per = 1) {
if (kk == N) cat("\r")
}
}
+
+# Temporary stopgap for converting 'SpatRaster' to 'im'
+## Modification of `as.im.RasterLayer` from `maptools` because `maptools` is retiring in 2023
+as.im.SpatRaster <- function (from, factor.col.name = NULL) {
+ if (!requireNamespace("spatstat.geom", quietly = TRUE)) {
+ stop(paste("package spatstat.geom required; please install it (or the full spatstat package) first"))
+ }
+ else {
+ spst_ver <- try(utils::packageVersion("spatstat"), silent = TRUE)
+ if (!inherits(spst_ver, "try-error") && spst_ver < 2 -
+ 0) {
+ stop(paste("You have an old version of spatstat installed which is",
+ " incompatible with spatstat.geom. Please update spatstat (or uninstall it).",
+ sep = ""))
+ }
+ }
+ if (!requireNamespace("sf", quietly = TRUE))
+ stop("package sf required for coercion")
+ if (!requireNamespace("terra", quietly = TRUE))
+ stop("package terra required for coercion")
+ if (!terra::hasValues(from))
+ stop("values required in SpatRaster object")
+ rs <- terra::res(from)
+ orig <- sf::st_bbox(from)[1:2] + 0.5 * rs
+ dm <- dim(from)[2:1]
+ xx <- unname(orig[1] + cumsum(c(0, rep(rs[1], dm[1] - 1))))
+ yy <- unname(orig[2] + cumsum(c(0, rep(rs[2], dm[2] - 1))))
+ val <- terra::values(from)
+ if (is.factor(from)) {
+ lev <- levels(from)[[1]]
+ if (!is.null(factor.col.name)) {
+ if (factor.col.name %in% colnames(lev)) {
+ factor.col <- which(colnames(lev) == factor.col.name)
+ }
+ else {
+ stop("'factor.col.name' is not a column name of the SpatRaster 'from'")
+ }
+ }
+ else {
+ factor.col <- length(lev)
+ }
+ val <- factor(val, levels = lev$ID, labels = lev[[factor.col]])
+ }
+ dim(val) <- dm
+ val <- spatstat.geom::transmat(val, from = list(x = "-i",
+ y = "j"), to = "spatstat")
+ im <- spatstat.geom::im(val, xcol = xx, yrow = yy)
+ return(im)
+}
diff --git a/README.md b/README.md
index e78d709..1c378d2 100644
--- a/README.md
+++ b/README.md
@@ -2,15 +2,18 @@ envi: Environmental Interpolation using Spatial Kernel Density Estimation
+[![R-CMD-check](https://github.com/lance-waller-lab/envi/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/lance-waller-lab/envi/actions/workflows/R-CMD-check.yaml)
[![CRAN status](http://www.r-pkg.org/badges/version/envi)](https://cran.r-project.org/package=envi)
[![CRAN version](https://www.r-pkg.org/badges/version-ago/envi)](https://cran.r-project.org/package=envi)
-[![CRAN RStudio mirror downloads](https://cranlogs.r-pkg.org/badges/grand-total/envi?color=blue)](https://r-pkg.org/pkg/envi)
+[![CRAN RStudio mirror downloads total](https://cranlogs.r-pkg.org/badges/grand-total/envi?color=blue)](https://r-pkg.org/pkg/envi)
+[![CRAN RStudio mirror downloads monthly ](http://cranlogs.r-pkg.org/badges/envi)](https://www.r-pkg.org:443/pkg/envi)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
![GitHub last commit](https://img.shields.io/github/last-commit/lance-waller-lab/envi)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5347826.svg)](https://doi.org/10.5281/zenodo.5347826)
+
-**Date repository last updated**: August 30, 2022
+**Date repository last updated**: December 16, 2022