Skip to content

Commit

Permalink
Update install/authenticate/initialize+docs
Browse files Browse the repository at this point in the history
 - fix bugged use of GOOGLE_APPLICATION_CREDENTIALS in context of service accounts
  • Loading branch information
brownag committed Jun 7, 2023
1 parent 260a44d commit 334d46a
Show file tree
Hide file tree
Showing 14 changed files with 149 additions and 57 deletions.
11 changes: 11 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -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()`
Expand Down
27 changes: 16 additions & 11 deletions R/hello.R
Original file line number Diff line number Diff line change
Expand Up @@ -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`
#'
Expand All @@ -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) {
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion R/install.R
Original file line number Diff line number Diff line change
Expand Up @@ -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()`
Expand Down
51 changes: 40 additions & 11 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ knitr::opts_chunk$set(
[![CRAN status](https://www.r-pkg.org/badges/version-last-release/rgeedim)](https://CRAN.R-project.org/package=rgeedim)
<!-- badges: end -->

{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.

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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)
Expand All @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -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(
Expand All @@ -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 |>
Expand All @@ -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')
Expand Down
100 changes: 71 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ status](https://www.r-pkg.org/badges/version-last-release/rgeedim)](https://CRAN
<!-- badges: end -->

{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.

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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,
Expand All @@ -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.

Expand Down Expand Up @@ -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(
Expand All @@ -338,13 +370,18 @@ y <- gd_properties(x)$id[1] |>
overwrite = TRUE,
silent = FALSE
)

plot(rast(y)[[1:4]])
```

<img src="man/figures/README-unnamed-chunk-7-1.jpeg" width="100%" />

``` 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 |>
Expand All @@ -361,10 +398,15 @@ z <- x |>
overwrite = TRUE,
silent = FALSE
)

plot(rast(z)[[1:4]])
```

<img src="man/figures/README-unnamed-chunk-7-2.jpeg" width="100%" />
<img src="man/figures/README-unnamed-chunk-8-1.jpeg" width="100%" />

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.
Binary file modified man/figures/README-inspect-1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified man/figures/README-unnamed-chunk-5-1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified man/figures/README-unnamed-chunk-6-1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified man/figures/README-unnamed-chunk-7-1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified man/figures/README-unnamed-chunk-7-2.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added man/figures/README-unnamed-chunk-8-1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 334d46a

Please sign in to comment.