diff --git a/NEWS.md b/NEWS.md
index 9d7027b..4e716bb 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,3 +1,14 @@
+# rgeedim 0.2.4
+
+ * Add `gd_task_status()` and `gd_task_uri()` for working with Task object produced by `gd_export()`
+
+ * Fix for `gd_composite()` and `gd_export()` errors when `region` argument is specified as an R spatial object (rather than GeoJSON-like list)
+
+ * Fix bug in `gd_enum_elements()` and add `gd_spectral_distance_metrics()`
+
+ * `gd_initialize()`: Fix use of illogical use of `GOOGLE_APPLICATION_CREDENTIALS` environment variable contents for Google Cloud service accounts under some conditions
+ - `EE_SERVICE_ACC_PRIVATE_KEY` is used for service accounts, whereas the former is used only for application credentials. `GOOGLE_APPLICATION_CREDENTIALS` is respected by `gd_authenticate()` `auth_mode` `"gcloud"` and `"appdefault"`.
+
# rgeedim 0.2.3
* For `gd_install()` `method="virtualenv"` or `method="conda"` if an environment of `envname` (default: `"r-reticulate"`) does not exist, it gets created before running `py_install()`
diff --git a/R/hello.R b/R/hello.R
index 7d3eb07..c8bd1f7 100644
--- a/R/hello.R
+++ b/R/hello.R
@@ -2,7 +2,7 @@
#'
#' Calls `geedim` `Initialize()` method. This method should be called at the beginning of each session.
#'
-#' @param private_key_file Optional: Path to JSON file containing client information and private key.
+#' @param private_key_file character. Optional: Path to JSON file containing client information and private key. Alternately, the contents of a JSON file. Instead of setting this argument you may specify `EE_SERVICE_ACC_PRIVATE_KEY` environment variable with path to JSON file.
#' @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`
#'
@@ -22,14 +22,11 @@ gd_initialize <- function(private_key_file = NULL, opt_url = 'https://earthengin
if (!is.null(private_key_file) && file.exists(private_key_file)) {
ek <- private_key_file
} else {
- # check possible places people would have a ref to private key
- env_keys <- c('GOOGLE_APPLICATION_CREDENTIALS', 'EE_SERVICE_ACC_PRIVATE_KEY')
+ # check places people would have a ref to service account key
ek <- NULL
- for (e in env_keys) {
- ev <- Sys.getenv(e, unset = NA_character_)
- if (!is.na(ev)) {
- ek <- ev
- }
+ ev <- Sys.getenv('EE_SERVICE_ACC_PRIVATE_KEY', unset = NA_character_)
+ if (!is.na(ev)) {
+ ek <- ev
}
}
if (!is.null(ek) && length(ek) == 1) {
@@ -65,11 +62,19 @@ gd_is_initialized <- function() {
#' Authenticate with Google Earth Engine using `gcloud`, "Notebook Authenticator" or other method
#'
-#' Calls `ee.Authenticate(...)` to authenticate with Earth Engine.
-#' @details This method should be called once to set up a machine/project with a particular authentication method. The `auth_mode="notebook"` argument is very convenient for interactive R use and will take you to a web page where you can sign into your Google Account and get a token to paste into a console prompt.
+#' Calls `ee.Authenticate(...)` to create a local instance of persistent credentials for Google Earth Engine. These credentials are used on subsequent calls to `ee.Initialize(...)` via `gd_initialize()`.
+#'
+#' @details This method should be called once to set up a machine/project with a particular authentication method.
+#'
+#' - `auth_mode="gcloud"` (default) fetches credentials using `gcloud`. Requires installation of command-line Google Cloud tools; see \url{https://cloud.google.com/cli} for details. This mode will open a web page where you can sign into your Google Account, then a local JSON file will be stored in `gcloud` configuration folder with your credentials. These credentials will be used by any library that requests Application Default Credentials (ADC) which are preferred for long-term storage.
+#'
+#' - `auth_mode="notebook"` argument is intended primarily for interactive or other short-term use. This mode will open a web page where you can sign into your Google Account to generate a short-term, revocable token to paste into the console prompt.
+#'
+#' - `auth_mode="appdefault"` mode uses locally stored credentials `gcloud` configuration stored in 'application_default_credentials.json' or JSON file specified by `GOOGLE_APPLICATION_CREDENTIALS` environment variable.
+
#' @param authorization_code Default: `NULL`
#' @param quiet Suppress warnings, errors, messages? Default: `FALSE`
-#' @param code_verifier Optional code verifier for security Default: `NULL`
+#' @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
diff --git a/R/install.R b/R/install.R
index b917828..1f1d328 100644
--- a/R/install.R
+++ b/R/install.R
@@ -5,7 +5,7 @@
#' configure custom environments with `pip=FALSE` and additional arguments
#' that are passed to `reticulate::py_install()`.
#'
-#' @param pip Use `pip` package manager? Default: `TRUE`. To use a virtual or conda environment specify `method="virtualenv"` or `method="conda`, respectively. See details.
+#' @param pip Use `pip` package manager? Default: `TRUE`. To use a virtual or conda environment specify `method="virtualenv"` or `method="conda"`, respectively. See details.
#' @param system Use a `system()` call to `python -m pip install --user ...` instead of `reticulate::py_install()`. Default: `FALSE`.
#' @param force Force update (uninstall/reinstall) and ignore existing installed packages? Default: `FALSE`. Applies to `pip=TRUE`.
#' @param ... Additional arguments passed to `reticulate::py_install()`
diff --git a/README.Rmd b/README.Rmd
index 7d11d62..41276cd 100644
--- a/README.Rmd
+++ b/README.Rmd
@@ -24,7 +24,7 @@ knitr::opts_chunk$set(
[](https://CRAN.R-project.org/package=rgeedim)
-{rgeedim} supports search and download of Google Earth Engine imagery with Python module [`geedim`](https://github.com/dugalh/geedim) by Dugal Harris. This package provides wrapper functions that make it more convenient to use `geedim` from R.
+{rgeedim} supports search and download of Google Earth Engine imagery with Python module [`geedim`](https://github.com/leftfield-geospatial/geedim) by Dugal Harris. This package provides wrapper functions that make it more convenient to use `geedim` from R.
The [rgeedim manual](https://humus.rocks/rgeedim/) describes the R API. See the [geedim manual]( https://geedim.readthedocs.io/) for more information on Python API and command line interface.
@@ -100,19 +100,27 @@ This example shows how to extract a Google Earth Engine asset by name for an arb
library(rgeedim)
```
-If this is your first time using any Google Earth Engine tools, authenticate with `gd_authenticate()`. You can pass arguments to use several different authorization methods. Perhaps the easiest to use is `auth_mode="notebook"` in that does not rely on an existing `GOOGLE_APPLICATION_CREDENTIALS` file nor an installation of the `gcloud` CLI tools. However, the other options are better for non-interactive use.
+If this is your first time using any Google Earth Engine tools, authenticate with `gd_authenticate()`. You can pass arguments to use several different authorization methods.
+
+Perhaps the easiest to use is `auth_mode="notebook"` in that does not rely on an existing `GOOGLE_APPLICATION_CREDENTIALS` file nor an installation of the `gcloud` CLI tools. However, the other options (using `gcloud` or a service account) are better for non-interactive or long-term use.
``` r
+# short duration token
gd_authenticate(auth_mode = "notebook")
```
+``` r
+# longer duration (default); requires gcloud command-line tools
+gd_authenticate(auth_mode = "gcloud")
+```
+
In each R session you will need to initialize the Earth Engine library
```{r}
gd_initialize()
```
-`gd_bbox()` is a simple function for specifying extents to {rgeedim} functions like `gd_download()`:
+Then you can select an extent of interest. `gd_bbox()` is a simple function for specifying extents to {rgeedim} functions like `gd_download()`.
``` {r}
r <- gd_bbox(
@@ -193,7 +201,11 @@ plot(c(dem, hillshade = hsd))
## Example: LiDAR Slope Map
-This example demonstrates how to access the 1m LiDAR data from USGS. A key step in this process is the use of `gd_composite()` to resample the component images prior to download.
+This example demonstrates how to access 1-meter LiDAR data from the USGS 3D Elevation Program (3DEP).
+
+There are other methods to derive an area of interest from existing spatial data sources, here we use `gd_region()` on a SpatVector object and pass resulting object to several functions that require a processing extent.
+
+LiDAR data are not available everywhere, and are generally available as collections of (tiled) layers. Therefore we use `gd_search()` to narrow down the options. The small sample extent covers only one tile. Additional filters on date and data quality are also possible with `gd_search()`. A key step in this process is the use of `gd_composite()` to resample the component images of interest from the collection on the server-side.
```{r}
library(rgeedim)
@@ -207,13 +219,22 @@ b <- 'POLYGON((-121.355 37.56,-121.355 37.555,
-121.35 37.555,-121.35 37.56,
-121.355 37.56))' |>
vect(crs = "OGC:CRS84")
+
+# create a GeoJSON-like list from a SpatVector object
+# (most rgeedim functions arguments for spatial inputs do this automatically)
r <- gd_region(b)
-# note that resampling is done on the images as part of compositing/before download
-x <- "USGS/3DEP/1m" |>
+# search collection for an area of interest
+a <- "USGS/3DEP/1m" |>
gd_collection_from_name() |>
- gd_search(region = r) |>
- gd_composite(resampling = "bilinear") |>
+ gd_search(region = r)
+
+# inspect individual image metadata in the collection
+gd_properties(a)
+
+# resampling images as part of composite; before download
+x <- a |>
+ gd_composite(resampling = "bilinear") |>
gd_download(region = r,
crs = "EPSG:5070",
scale = 1,
@@ -229,7 +250,9 @@ plot(project(b, x), add = TRUE)
## Example: Landsat-7 cloud/shadow-free composite
-This example demonstrates download of a Landsat-7 cloud/shadow-free composite image. A collection is created from the USGS Landsat 7 Level 2, Collection 2, Tier 1. This example is based on a [tutorial](https://geedim.readthedocs.io/en/latest/examples/l7_composite.html) in the `geedim` manual.
+This example demonstrates download of a Landsat-7 cloud/shadow-free composite image. A collection is created from the NASA/USGS Landsat 7 Level 2, Collection 2, Tier 1.
+
+This example is based on a [tutorial](https://geedim.readthedocs.io/en/latest/examples/l7_composite.html) in the `geedim` manual.
```{r}
library(rgeedim)
@@ -258,7 +281,7 @@ x <- 'LANDSAT/LE07/C02/T1_L2' |>
# inspect individual image metadata in the collection
gd_properties(x)
-# download a single image
+# download a single image, no compositing
y <- gd_properties(x)$id[1] |>
gd_image_from_id() |>
gd_download(
@@ -270,8 +293,13 @@ y <- gd_properties(x)$id[1] |>
overwrite = TRUE,
silent = FALSE
)
+
plot(rast(y)[[1:4]])
+```
+
+Now we have several images of interest, and also major issues with some of the inputs. In this case there were failures of sensors on the Landsat satellite, but other data gaps may occur due to masked cloudy areas or due to patchy coverage of the source product.
+```{r}
# create composite landsat image near December 1st, 2020 and download
# using q-mosaic method.
z <- x |>
@@ -288,10 +316,11 @@ z <- x |>
overwrite = TRUE,
silent = FALSE
)
+
plot(rast(z)[[1:4]])
```
-The `"q-mosaic"` method produces a composite largely free of artifacts; this is because it prioritizes pixels with higher distance from clouds.
+The `"q-mosaic"` method produces a composite (largely) free of artifacts in this case; this is because it prioritizes pixels with higher distance from clouds to fill in the gaps. Other methods are available such as `"medoid"`; this may give better results when compositing more contrasting inputs such as several dates over a time period where vegetation or other cover changes appreciably.
```{r include=FALSE}
unlink('image.tif')
diff --git a/README.md b/README.md
index 4576d1d..36932dd 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,8 @@ status](https://www.r-pkg.org/badges/version-last-release/rgeedim)](https://CRAN
{rgeedim} supports search and download of Google Earth Engine imagery
-with Python module [`geedim`](https://github.com/dugalh/geedim) by Dugal
+with Python module
+[`geedim`](https://github.com/leftfield-geospatial/geedim) by Dugal
Harris. This package provides wrapper functions that make it more
convenient to use `geedim` from R.
@@ -114,29 +115,38 @@ expressed in WGS84 decimal degrees (`"OGC:CRS84"`).
``` r
library(rgeedim)
-#> rgeedim v0.2.3 -- using geedim 1.7.0 w/ earthengine-api 0.1.347
+#> rgeedim v0.2.4 -- using geedim 1.7.1 w/ earthengine-api 0.1.355
```
If this is your first time using any Google Earth Engine tools,
authenticate with `gd_authenticate()`. You can pass arguments to use
-several different authorization methods. Perhaps the easiest to use is
-`auth_mode="notebook"` in that does not rely on an existing
-`GOOGLE_APPLICATION_CREDENTIALS` file nor an installation of the
-`gcloud` CLI tools. However, the other options are better for
-non-interactive use.
+several different authorization methods.
+
+Perhaps the easiest to use is `auth_mode="notebook"` in that does not
+rely on an existing `GOOGLE_APPLICATION_CREDENTIALS` file nor an
+installation of the `gcloud` CLI tools. However, the other options
+(using `gcloud` or a service account) are better for non-interactive or
+long-term use.
``` r
+# short duration token
gd_authenticate(auth_mode = "notebook")
```
+``` r
+# longer duration (default); requires gcloud command-line tools
+gd_authenticate(auth_mode = "gcloud")
+```
+
In each R session you will need to initialize the Earth Engine library
``` r
gd_initialize()
```
-`gd_bbox()` is a simple function for specifying extents to {rgeedim}
-functions like `gd_download()`:
+Then you can select an extent of interest. `gd_bbox()` is a simple
+function for specifying extents to {rgeedim} functions like
+`gd_download()`.
``` r
r <- gd_bbox(
@@ -174,12 +184,7 @@ where data are available).
``` r
library(terra)
-#> terra 1.7.18
-#> WARNING: different compile-time and run-time versions of GEOS
-#> Compiled with:3.11.2-CAPI-1.17.2
-#> Running with:3.11.1-CAPI-1.17.1
-#>
-#> You should reinstall package 'terra'
+#> terra 1.7.33
f <- rast(res)
f
@@ -243,9 +248,21 @@ plot(c(dem, hillshade = hsd))
## Example: LiDAR Slope Map
-This example demonstrates how to access the 1m LiDAR data from USGS. A
-key step in this process is the use of `gd_composite()` to resample the
-component images prior to download.
+This example demonstrates how to access 1-meter LiDAR data from the USGS
+3D Elevation Program (3DEP).
+
+There are other methods to derive an area of interest from existing
+spatial data sources, here we use `gd_region()` on a SpatVector object
+and pass resulting object to several functions that require a processing
+extent.
+
+LiDAR data are not available everywhere, and are generally available as
+collections of (tiled) layers. Therefore we use `gd_search()` to narrow
+down the options. The small sample extent covers only one tile.
+Additional filters on date and data quality are also possible with
+`gd_search()`. A key step in this process is the use of `gd_composite()`
+to resample the component images of interest from the collection on the
+server-side.
``` r
library(rgeedim)
@@ -259,13 +276,26 @@ b <- 'POLYGON((-121.355 37.56,-121.355 37.555,
-121.35 37.555,-121.35 37.56,
-121.355 37.56))' |>
vect(crs = "OGC:CRS84")
+
+# create a GeoJSON-like list from a SpatVector object
+# (most rgeedim functions arguments for spatial inputs do this automatically)
r <- gd_region(b)
-# note that resampling is done on the images as part of compositing/before download
-x <- "USGS/3DEP/1m" |>
+# search collection for an area of interest
+a <- "USGS/3DEP/1m" |>
gd_collection_from_name() |>
- gd_search(region = r) |>
- gd_composite(resampling = "bilinear") |>
+ gd_search(region = r)
+
+# inspect individual image metadata in the collection
+gd_properties(a)
+#> id
+#> 1 USGS/3DEP/1m/USGS_1M_10_x64y416_CA_UpperSouthAmerican_Eldorado_2019_B19
+#> date
+#> 1 2005-12-31 16:00:00
+
+# resampling images as part of composite; before download
+x <- a |>
+ gd_composite(resampling = "bilinear") |>
gd_download(region = r,
crs = "EPSG:5070",
scale = 1,
@@ -284,8 +314,10 @@ plot(project(b, x), add = TRUE)
## Example: Landsat-7 cloud/shadow-free composite
This example demonstrates download of a Landsat-7 cloud/shadow-free
-composite image. A collection is created from the USGS Landsat 7 Level
-2, Collection 2, Tier 1. This example is based on a
+composite image. A collection is created from the NASA/USGS Landsat 7
+Level 2, Collection 2, Tier 1.
+
+This example is based on a
[tutorial](https://geedim.readthedocs.io/en/latest/examples/l7_composite.html)
in the `geedim` manual.
@@ -326,7 +358,7 @@ gd_properties(x)
#> 3 99.93 5.44 145.16 23.71
#> 4 99.91 5.73 138.46 30.91
-# download a single image
+# download a single image, no compositing
y <- gd_properties(x)$id[1] |>
gd_image_from_id() |>
gd_download(
@@ -338,13 +370,18 @@ y <- gd_properties(x)$id[1] |>
overwrite = TRUE,
silent = FALSE
)
+
plot(rast(y)[[1:4]])
```
-``` r
+Now we have several images of interest, and also major issues with some
+of the inputs. In this case there were failures of sensors on the
+Landsat satellite, but other data gaps may occur due to masked cloudy
+areas or due to patchy coverage of the source product.
+``` r
# create composite landsat image near December 1st, 2020 and download
# using q-mosaic method.
z <- x |>
@@ -361,10 +398,15 @@ z <- x |>
overwrite = TRUE,
silent = FALSE
)
+
plot(rast(z)[[1:4]])
```
-
+
-The `"q-mosaic"` method produces a composite largely free of artifacts;
-this is because it prioritizes pixels with higher distance from clouds.
+The `"q-mosaic"` method produces a composite (largely) free of artifacts
+in this case; this is because it prioritizes pixels with higher distance
+from clouds to fill in the gaps. Other methods are available such as
+`"medoid"`; this may give better results when compositing more
+contrasting inputs such as several dates over a time period where
+vegetation or other cover changes appreciably.
diff --git a/man/figures/README-inspect-1.jpeg b/man/figures/README-inspect-1.jpeg
index ba99763..dd35894 100644
Binary files a/man/figures/README-inspect-1.jpeg and b/man/figures/README-inspect-1.jpeg differ
diff --git a/man/figures/README-unnamed-chunk-5-1.jpeg b/man/figures/README-unnamed-chunk-5-1.jpeg
index 330b0f0..5bb71fa 100644
Binary files a/man/figures/README-unnamed-chunk-5-1.jpeg and b/man/figures/README-unnamed-chunk-5-1.jpeg differ
diff --git a/man/figures/README-unnamed-chunk-6-1.jpeg b/man/figures/README-unnamed-chunk-6-1.jpeg
index 87fee9f..1c71b3c 100644
Binary files a/man/figures/README-unnamed-chunk-6-1.jpeg and b/man/figures/README-unnamed-chunk-6-1.jpeg differ
diff --git a/man/figures/README-unnamed-chunk-7-1.jpeg b/man/figures/README-unnamed-chunk-7-1.jpeg
index ca10992..2b40725 100644
Binary files a/man/figures/README-unnamed-chunk-7-1.jpeg and b/man/figures/README-unnamed-chunk-7-1.jpeg differ
diff --git a/man/figures/README-unnamed-chunk-7-2.jpeg b/man/figures/README-unnamed-chunk-7-2.jpeg
index 1c6355e..6ece5c9 100644
Binary files a/man/figures/README-unnamed-chunk-7-2.jpeg and b/man/figures/README-unnamed-chunk-7-2.jpeg differ
diff --git a/man/figures/README-unnamed-chunk-8-1.jpeg b/man/figures/README-unnamed-chunk-8-1.jpeg
new file mode 100644
index 0000000..6ece5c9
Binary files /dev/null and b/man/figures/README-unnamed-chunk-8-1.jpeg differ
diff --git a/man/gd_authenticate.Rd b/man/gd_authenticate.Rd
index f99b1e9..cc6abab 100644
--- a/man/gd_authenticate.Rd
+++ b/man/gd_authenticate.Rd
@@ -16,7 +16,7 @@ gd_authenticate(
\item{quiet}{Suppress warnings, errors, messages? Default: \code{FALSE}}
-\item{code_verifier}{Optional code verifier for security Default: \code{NULL}}
+\item{code_verifier}{Optional code verifier for security. Default: \code{NULL}}
\item{auth_mode}{One of \code{"notebook"}, \code{"gcloud"}, \code{"appdefault"} or (default) \code{NULL} to guess based on the environment}
}
@@ -24,10 +24,15 @@ gd_authenticate(
This function is primarily used for the side-effect of authentication with the 'Google Earth Engine' servers. Invisibly returns \code{try-error} on error.
}
\description{
-Calls \code{ee.Authenticate(...)} to authenticate with Earth Engine.
+Calls \code{ee.Authenticate(...)} to create a local instance of persistent credentials for Google Earth Engine. These credentials are used on subsequent calls to \code{ee.Initialize(...)} via \code{gd_initialize()}.
}
\details{
-This method should be called once to set up a machine/project with a particular authentication method. The \code{auth_mode="notebook"} argument is very convenient for interactive R use and will take you to a web page where you can sign into your Google Account and get a token to paste into a console prompt.
+This method should be called once to set up a machine/project with a particular authentication method.
+\itemize{
+\item \code{auth_mode="gcloud"} (default) fetches credentials using \code{gcloud}. Requires installation of command-line Google Cloud tools; see \url{https://cloud.google.com/cli} for details. This mode will open a web page where you can sign into your Google Account, then a local JSON file will be stored in \code{gcloud} configuration folder with your credentials. These credentials will be used by any library that requests Application Default Credentials (ADC) which are preferred for long-term storage.
+\item \code{auth_mode="notebook"} argument is intended primarily for interactive or other short-term use. This mode will open a web page where you can sign into your Google Account to generate a short-term, revocable token to paste into the console prompt.
+\item \code{auth_mode="appdefault"} mode uses locally stored credentials \code{gcloud} configuration stored in 'application_default_credentials.json' or JSON file specified by \code{GOOGLE_APPLICATION_CREDENTIALS} environment variable.
+}
}
\examples{
\dontrun{
diff --git a/man/gd_initialize.Rd b/man/gd_initialize.Rd
index 429ceea..45a9a51 100644
--- a/man/gd_initialize.Rd
+++ b/man/gd_initialize.Rd
@@ -14,7 +14,7 @@ gd_initialize(
gd_is_initialized()
}
\arguments{
-\item{private_key_file}{Optional: Path to JSON file containing client information and private key.}
+\item{private_key_file}{character. Optional: Path to JSON file containing client information and private key. Alternately, the contents of a JSON file. Instead of setting this argument you may specify \code{EE_SERVICE_ACC_PRIVATE_KEY} environment variable with path to JSON file.}
\item{opt_url}{Base URL for API requests; defaults to "High Volume": \code{"https://earthengine-highvolume.googleapis.com"}}
diff --git a/man/gd_install.Rd b/man/gd_install.Rd
index 2371bbf..502c9e4 100644
--- a/man/gd_install.Rd
+++ b/man/gd_install.Rd
@@ -7,7 +7,7 @@
gd_install(pip = TRUE, system = FALSE, force = FALSE, ...)
}
\arguments{
-\item{pip}{Use \code{pip} package manager? Default: \code{TRUE}. To use a virtual or conda environment specify \code{method="virtualenv"} or \verb{method="conda}, respectively. See details.}
+\item{pip}{Use \code{pip} package manager? Default: \code{TRUE}. To use a virtual or conda environment specify \code{method="virtualenv"} or \code{method="conda"}, respectively. See details.}
\item{system}{Use a \code{system()} call to \verb{python -m pip install --user ...} instead of \code{reticulate::py_install()}. Default: \code{FALSE}.}