Skip to content

Commit

Permalink
CRAN Release 0.1.0 (#3)
Browse files Browse the repository at this point in the history
* for CRAN

* Add `gd_is_initialized()`

* Add CRAN installation instructions

* System requirements are Python >=3.6 (for 'geedim')

* Spelling

* squote

* squote (2)

* link

* docs

* fix

* docs

* donttest: gd_initialize() can take several seconds by itself

* refactor ee usage to avoid notes

* alt test for geedim presence in tests (does not invoke load of missing module)
  • Loading branch information
brownag authored Nov 2, 2022
1 parent 772321f commit 5259f43
Show file tree
Hide file tree
Showing 31 changed files with 379 additions and 64 deletions.
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ $\.github/*
^\.github$
^misc$
^cran-comments\.md$
^CRAN-SUBMISSION$
10 changes: 6 additions & 4 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
Package: rgeedim
Type: Package
Title: Search, Composite, and Download Google Earth Engine Imagery with the Python Module 'geedim'
Title: Search, Composite, and Download 'Google Earth Engine' Imagery with the 'Python' Module 'geedim'
Version: 0.1.0
Author: Andrew Brown
Authors@R: c(person("Andrew", "Brown", role = c("aut", "cre"), email = "[email protected]"))
Maintainer: Andrew Brown <[email protected]>
URL: https://humus.rocks/rgeedim/, https://github.com/brownag/rgeedim, https://geedim.readthedocs.io/
BugReports: https://github.com/brownag/rgeedim/issues
Description: Search, composite, and download Google Earth Engine imagery with 'reticulate' bindings for the Python module 'geedim'.
Wrapper functions are provided to make it more convenient to use 'geedim' to download images larger than the Earth Engine size limit.
Description: Search, composite, and download 'Google Earth Engine' imagery with 'reticulate' bindings for the 'Python' module 'geedim'. Read the 'geedim' documentation here: <https://geedim.readthedocs.io/>.
Wrapper functions are provided to make it more convenient to use 'geedim' to download images larger than the 'Google Earth Engine' size limit <https://developers.google.com/earth-engine/apidocs/ee-image-getdownloadurl>.
By default the "High Volume" API endpoint <https://developers.google.com/earth-engine/cloud/highvolume> is used to download data and this URL can be customized during initialization of the package.
SystemRequirements: Python (>= 3.6.0)
Config/reticulate:
list(
packages = list(
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export(gd_enum_names)
export(gd_footprint)
export(gd_image_from_id)
export(gd_initialize)
export(gd_is_initialized)
export(gd_mask_clouds)
export(gd_projection)
export(gd_properties)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

* `gd_region()` now supports more complex SpatVector geometries (no longer uses extent to form bounding box if `x` is SpatVector or can be converted to one)

* Add `gd_is_initialized()` and use for examples and other conditional evaluation of code that requires authentication and initialized 'Google Earth Engine' resources

# rgeedim 0.0.0.9008

* Renamed `gd_bandnames()` -> `gd_band_names()`
Expand Down
6 changes: 1 addition & 5 deletions R/AAAA.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
gd <- NULL
ee <- NULL
collections_module <- NULL

#' `Module(geedim)` - Get `geedim` Module Instance
Expand All @@ -26,7 +25,7 @@ gd_version <- function() {
#'
#' @export
earthengine <- function() {
ee
gd$utils$ee
}

#' @description `gd_ee_version()` Gets the `ee` version using `importlib.metadata.version()`
Expand All @@ -51,9 +50,6 @@ gd_ee_version <- function() {

if (is.null(gd)) {
try(gd <<- reticulate::import("geedim", delay_load = TRUE), silent = TRUE)
if (length(gd) > 0) {
try(ee <<- gd$utils$ee, silent = TRUE)
}
}

try(reticulate::py_run_string("from importlib.metadata import version"), silent = TRUE)
Expand Down
15 changes: 14 additions & 1 deletion R/composite.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,21 @@
#' @param ... [additional arguments](https://geedim.readthedocs.io/en/latest/_generated/geedim.collection.MaskedCollection.composite.html) to `geedim.collection.MaskedCollection$composite()`
#' @return a composite `geedim.mask.MaskedImage` object
#' @export
#' @examplesIf gd_is_initialized() && requireNamespace("terra")
#' @examples
#' \donttest{
#' b <- terra::vect('POLYGON((-121.355 37.56,-121.355 37.555,
#' -121.35 37.555,-121.35 37.56,
#' -121.355 37.56))',
#' crs = "OGC:CRS84")
#'
#' if (gd_is_initialized())
#' gd_composite(gd_search(gd_collection_from_name("USGS/3DEP/1m"),
#' region = gd_region(b)),
#' resampling = "bilinear")
#' }
gd_composite <- function(x, ...) {
if (!inherits(x, 'geedim.collection.MaskedCollection')){
if (!inherits(x, 'geedim.collection.MaskedCollection')) {
stop("`x` should be a geedim.collection.MaskedCollection", call. = FALSE)
}
y <- try(x$composite(...), silent = TRUE)
Expand Down
29 changes: 29 additions & 0 deletions R/download.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,35 @@
#' @seealso `gd_region()` `gd_bbox()`
#' @return Invisible path to downloaded image, or `try-error` on error
#' @export
#' @examplesIf gd_is_initialized()
#' @examples
#' \donttest{
#' r <- gd_bbox(
#' xmin = -121,
#' xmax = -120.5,
#' ymin = 38.5,
#' ymax = 39
#' )
#'
#' if (gd_is_initialized()) {
#' x <- gd_image_from_id('CSP/ERGo/1_0/Global/SRTM_topoDiversity')
#' tf <- tempfile(fileext = ".tif")
#'
#' # fast sample download at 10x aggregation (900m v.s. 90m)
#' img <- gd_download(x, filename = tf,
#' region = r, scale = 900,
#' overwrite = TRUE, silent = FALSE)
#'
#' if (requireNamespace("terra")) {
#' library(terra)
#' f <- rast(img)
#' plot(f[[1]])
#' # inspect object
#' f
#' }
#' unlink(tf)
#' }
#' }
gd_download <- function(x,
filename = tempfile(fileext = ".tif"),
region = NULL,
Expand Down
29 changes: 29 additions & 0 deletions R/enums.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
#' @return `gd_enum_names()`: character vector containing names of Enums
#' @export
#' @rdname enum
#' @examples
#' \donttest{
#' if (gd_is_initialized())
#' gd_enum_names()
#' }
gd_enum_names <- function() {
n <- names(gd$enums)
n[which(n != "Enum")]
Expand All @@ -13,6 +18,12 @@ gd_enum_names <- function() {
#' @return `gd_enum_elements()`: element values of an Enum
#' @export
#' @rdname enum
#' @examplesIf gd_is_initialized()
#' @examples
#' \donttest{
#' if (gd_is_initialized())
#' gd_enum_elements()
#' }
gd_enum_elements <- function(enum = gd_enum_names()) {
enum <- match.arg(enum, gd_enum_names(), several.ok = TRUE)
res <- lapply(enum, \(x) {
Expand All @@ -26,20 +37,38 @@ gd_enum_elements <- function(enum = gd_enum_names()) {
#' @return `gd_resampling_methods()`: character vector of resampling methods (Enum `"ResamplingMethod"`)
#' @export
#' @rdname enum
#' @examplesIf gd_is_initialized()
#' @examples
#' \donttest{
#' if (gd_is_initialized())
#' gd_resampling_methods()
#' }
gd_resampling_methods <- function() {
gd_enum_elements("ResamplingMethod")[[1]]
}

#' @return `gd_cloud_mask_methods()`: character vector of cloud mask methods (Enum `"CloudMaskMethod"`)
#' @export
#' @rdname enum
#' @examplesIf gd_is_initialized()
#' @examples
#' \donttest{
#' if (gd_is_initialized())
#' gd_cloud_mask_methods()
#' }
gd_cloud_mask_methods <- function() {
gd_enum_elements("CloudMaskMethod")[[1]]
}

#' @return `gd_composite_methods()`: character vector of composite methods (Enum `"CompositeMethod"`)
#' @export
#' @rdname enum
#' @examplesIf gd_is_initialized()
#' @examples
#' \donttest{
#' if (gd_is_initialized())
#' gd_composite_methods()
#' }
gd_composite_methods <- function() {
gd_enum_elements("CompositeMethod")[[1]]
}
15 changes: 15 additions & 0 deletions R/from.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
#'
#' @export
#' @rdname from
#' @examplesIf gd_is_initialized()
#' \donttest{
#' if (gd_is_initialized())
#' gd_image_from_id('CSP/ERGo/1_0/Global/SRTM_topoDiversity')
#' }
gd_image_from_id <- function(x) {
y <- try(gd$MaskedImage$from_id(x), silent = FALSE)
if (inherits(y, 'try-error')) return(invisible(y))
Expand All @@ -16,6 +21,11 @@ gd_image_from_id <- function(x) {

#' @export
#' @rdname from
#' @examplesIf gd_is_initialized()
#' \donttest{
#' if (gd_is_initialized())
#' gd_collection_from_name("USGS/3DEP/1m")
#' }
gd_collection_from_name <- function(x) {
y <- try(gd$MaskedCollection$from_name(x), silent = FALSE)
if (inherits(y, 'try-error')) return(invisible(y))
Expand All @@ -24,6 +34,11 @@ gd_collection_from_name <- function(x) {

#' @export
#' @rdname from
#' @examplesIf gd_is_initialized()
#' \donttest{
#' if (gd_is_initialized())
#' gd_collection_from_list(c("USGS/3DEP/1m", "USGS/NED"))
#' }
gd_collection_from_list <- function(x) {
y <- try(gd$MaskedCollection$from_list(x), silent = FALSE)
if (inherits(y, 'try-error')) return(invisible(y))
Expand Down
29 changes: 20 additions & 9 deletions R/hello.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
#' @param opt_url Base URL for API requests; defaults to "High Volume": `"https://earthengine-highvolume.googleapis.com"`
#' @param quiet Suppress error messages on load? Default: `FALSE`
#'
#' @return try-error (invisibly) on error
#' @return `gd_initialize()`: try-error (invisibly) on error.
#' @export
#' @importFrom reticulate py_run_string
#' @importFrom jsonlite read_json
#' @seealso `gd_authenticate()`
#' @examples
#' \dontrun{
#' \donttest{
#' gd_initialize()
#' }
gd_initialize <- function(private_key_file = NULL, opt_url = 'https://earthengine-highvolume.googleapis.com', quiet = FALSE) {
gd_initialize <- function(private_key_file = NULL, opt_url = 'https://earthengine-highvolume.googleapis.com', quiet = TRUE) {
# python 3.10.x compatibility:
try(collections_module$Callable <- collections_module$abc$Callable, silent = TRUE)

Expand All @@ -40,20 +40,29 @@ gd_initialize <- function(private_key_file = NULL, opt_url = 'https://earthengin
kd <- jsonlite::parse_json(ek)
}

sac <- try(ee$ServiceAccountCredentials(kd[['client_email']],
key_data = kd[['private_key']]),
sac <- try(gd$utils$ee$ServiceAccountCredentials(kd[['client_email']],
key_data = kd[['private_key']]),
silent = quiet)

if (inherits(sac, 'try-error')) {
return(invisible(sac))
}

return(invisible(try(ee$Initialize(sac, opt_url = opt_url), silent = quiet)))
return(invisible(try(gd$utils$ee$Initialize(sac, opt_url = opt_url), silent = quiet)))
} else {
return(invisible(try(ee$Initialize(opt_url = opt_url), silent = quiet)))
return(invisible(try(gd$utils$ee$Initialize(opt_url = opt_url), silent = quiet)))
}
}

#' @export
#' @return `gd_is_initialized()`: logical. `TRUE` if initialized successfully.
#' @rdname gd_initialize
#' @examples
#' gd_is_initialized()
gd_is_initialized <- function() {
return(length(geedim()) > 0 && !inherits(gd_initialize(), "try-error"))
}

#' Authenticate with Google Earth Engine using `gcloud`, "Notebook Authenticator" or other method
#'
#' Calls `ee.Authenticate(...)` to authenticate with Earth Engine.
Expand All @@ -62,13 +71,15 @@ gd_initialize <- function(private_key_file = NULL, opt_url = 'https://earthengin
#' @param quiet Suppress warnings, errors, messages? Default: `FALSE`
#' @param code_verifier Optional code verifier for security Default: `NULL`
#' @param auth_mode One of `"notebook"`, `"gcloud"`, `"appdefault"` or (default) `NULL` to guess based on the environment
#' @return This function is primarily used for the side-effect of authentication with the 'Google Earth Engine' servers. Invisibly returns `try-error` on error.
#' @export
#' @examples
#' \dontrun{
#' gd_authenticate(auth_mode="notebook")
#' # opens web page to complete authentication/provide authorization code
#' gd_authenticate(auth_mode = "notebook")
#' }
gd_authenticate <- function(authorization_code = NULL, quiet = FALSE, code_verifier = NULL, auth_mode = NULL) {
invisible(try(ee$Authenticate(
invisible(try(gd$utils$Authenticate(
authorization_code = authorization_code,
quiet = quiet,
code_verifier = code_verifier,
Expand Down
7 changes: 6 additions & 1 deletion R/projection.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@
#'
#' @return `ee.Projection` object
#' @export
#' @examplesIf gd_is_initialized()
#' \donttest{
#' if (gd_is_initialized())
#' gd_projection(gd_image_from_id('CSP/ERGo/1_0/Global/SRTM_topoDiversity'))
#' }
gd_projection <- function(x) {
if (!inherits(x, "ee.image.Image")) {
if (inherits(x, 'geedim.download.BaseImage')) {
gd$utils$get_projection(x$ee_image)
} else {
gd$utils$get_projection(ee$Image(x))
gd$utils$get_projection(gd$utils$ee$Image(x))
}
} else {
gd$utils$get_projection(x)
Expand Down
7 changes: 7 additions & 0 deletions R/regions.R
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ gd_bbox <- function(...) {
#' @return list representing a GeoJSON extent
#' @importFrom methods as
#' @export
#' @examplesIf requireNamespace("terra")
#' @examples
#' b <- terra::vect('POLYGON((-121.355 37.56,-121.355 37.555,
#' -121.35 37.555,-121.35 37.56,
#' -121.355 37.56))',
#' crs = "OGC:CRS84")
#' gd_region(b)
gd_region <- function(x) {

if (is.list(x) &&
Expand Down
Loading

0 comments on commit 5259f43

Please sign in to comment.