Skip to content

Commit c7ffbf4

Browse files
authored
Merge pull request #88 from r-spatial/v.1.0.4
working in rgee v.1.0.4
2 parents 0d6c1ba + 43b0adb commit c7ffbf4

File tree

10 files changed

+343
-63
lines changed

10 files changed

+343
-63
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: rgee
22
Title: R Bindings for Calling the 'Earth Engine' API
3-
Version: 1.0.3
3+
Version: 1.0.4
44
Authors@R:
55
c(person(given = "Cesar",
66
family = "Aybar",

NEWS.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,22 @@ vignette: >
1111
%\VignetteIndexEntry{NEWS}
1212
%\VignetteEncoding{UTF-8}
1313
---
14+
# rgee 1.0.4
15+
- Add `ee_help` a new Rstudio addins that mimics the help Rstudio interface (F1).
16+
- Fix a bug that makes that `ee_as_sf` only supports `GeoJSON` format.
17+
- If `dsn` is not specified in `ee_as_sf`, it will create a temporary shapefile (in \tmp dir).
18+
- Fix a bug in `ee_imagecollection_to_local` (#87 Thanks @cedlfc44)
19+
- Fix a bug in `ee_image_local` (#88 Thanks @cedlfc44)
20+
- Fix a bug in `ee_create_credentials_drive` (#90 #78 Thanks @cedlfc44)
21+
22+
# rgee 1.0.3
23+
- getPass library removed from `ee_Initialize`.
24+
- New argument `display` in `ee_Initialize` to return the authentication URI. Useful for `rgee` colab users.
25+
- Changes in some diagnostic messages to make possible to use `rgee` in colab.
26+
- `ee_help` returns a HTML file rather than TRUE. It also now supports characters (e.g. `ee_help("ee$Image")`).
27+
- Fix a strange bug when `ee_Initialize` tries to connect to reticulate the first time.
28+
- Fix small bugs in `ee_user_info` and `ee_users`
29+
1430
# rgee 1.0.2
1531
- Earth Engine Python API updated to 0.1.229.
1632
- Fix a bug in `ee_Initialize`, that does not permit users to use `ee_createAssetHome` to define their *Earth Engine Assets home root folder*

R/addins.R

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#' Return documentation of Earth Engine modules, methods and classes
2+
#' @noRd
3+
ee_help_addins <- function() {
4+
context <- rstudioapi::getSourceEditorContext()
5+
selected_content <- context$selection[[1]]$text
6+
if (selected_content == "") {
7+
try(ee_help(ee_get_eefunc()), silent = TRUE)
8+
} else {
9+
selected_content_filtered <- gsub("\n|[[:space:]]","", selected_content)
10+
try(ee_help(selected_content_filtered), silent = TRUE)
11+
}
12+
}
13+
14+
#' How many white space we deleted?
15+
#' @noRd
16+
ee_space_removed <- function(text, cursor) {
17+
text <- strsplit(text,"")[[1]]
18+
sum(grepl(" ",text[1:cursor]))
19+
}
20+
21+
#' Merge forward and backward
22+
#' @noRd
23+
ee_get_funname <- function(text, cursor) {
24+
text <- strsplit(text,"")[[1]]
25+
26+
if (length(text) < cursor) {
27+
return(invisible(FALSE))
28+
}
29+
30+
if (text[cursor] == "(") {
31+
cursor <- cursor -1
32+
}
33+
if (cursor == 1) {
34+
# the last word can not be a $
35+
paste0(text[1:forward(text, cursor)], collapse = "")
36+
} else {
37+
# the last word can not be a $
38+
paste0(text[backward(text, cursor):forward(text, cursor)], collapse = "")
39+
}
40+
}
41+
42+
#' Search words forward
43+
#' @noRd
44+
forward <- function(x, cursor) {
45+
forward_range <- cursor:length(x)
46+
for (index in forward_range) {
47+
is_letter <- grepl("[a-zA-Z]", x[index])
48+
if (!is_letter) {
49+
index <- index - 1
50+
break
51+
}
52+
}
53+
if (is_letter <- grepl("\\$", x[index])) {
54+
index - 1
55+
} else {
56+
index
57+
}
58+
}
59+
60+
#' Search words backward
61+
#' @noRd
62+
backward <- function(x, cursor) {
63+
index <- cursor
64+
repeat {
65+
if (index == 1) {
66+
break
67+
}
68+
69+
# Just pass the letter if is inside a ()
70+
if (x[index] == ")") {
71+
count_par <- 1
72+
counter <- 0
73+
while (count_par != 0) {
74+
if (x[index] == "(") {
75+
count_par <- count_par - 1
76+
} else if(x[index] == ")" & counter != 0) {
77+
count_par <- count_par + 1
78+
}
79+
index <- index - 1
80+
counter <- counter + 1
81+
if (index == 1) {
82+
break
83+
}
84+
# print(sprintf("%s:%s",counter,count_par))
85+
}
86+
index <- index - 1
87+
}
88+
89+
if (grepl("[a-zA-Z]|\\$|\\)", x[index])) {
90+
index <- index - 1
91+
} else {
92+
index <- index + 1
93+
break
94+
}
95+
}
96+
index
97+
}
98+
99+
#' Aux function useful to know if a multiline (recursive)
100+
#' Returns a logical vector.
101+
#' @noRd
102+
is_multilines_r <- function(context, line) {
103+
if (is_multilines(context, line)) {
104+
c(TRUE, is_multilines_r(context, line - 1))
105+
} else {
106+
FALSE
107+
}
108+
}
109+
110+
#' Aux function useful to know if a multiline
111+
#' Returns a logical value.
112+
#' @noRd
113+
is_multilines <- function(context, line) {
114+
if (line == 1) {
115+
FALSE
116+
} else {
117+
line_of_code_1 <- context$contents[line]
118+
text_1 <- strsplit(line_of_code_1, "")[[1]]
119+
is_white_space <- text_1[1] == " "
120+
121+
line_of_code_2 <- context$contents[line - 1]
122+
text_2 <- strsplit(line_of_code_2, "")[[1]]
123+
is_dolar <- text_2[length(text_2)] == "$"
124+
if (length(is_dolar ) == 0) {
125+
is_dolar <- FALSE
126+
}
127+
128+
if (is_dolar & is_white_space) {
129+
TRUE
130+
} else {
131+
FALSE
132+
}
133+
}
134+
}
135+
136+
#' Returns the EE function name
137+
#' @noRd
138+
ee_get_eefunc <- function() {
139+
# get rstudio context
140+
context <- rstudioapi::getSourceEditorContext()
141+
cursor <- context$selection[[1]]$range[[1]][2]
142+
line <- context$selection[[1]]$range[[1]][1]
143+
144+
# is a multiple line?
145+
if (any(is_multilines_r(context, line))) {
146+
# lines above!
147+
number_of_extra_lineas <- sum(is_multilines_r(context, line))
148+
lines <- (line - number_of_extra_lineas):line
149+
# merge lines text in one character
150+
text_merge <- paste0(gsub(" ", "", context$contents[lines]), collapse = "")
151+
# upgrade cursor
152+
extra_lines <- lines[-length(lines)]
153+
previous_len <- paste0(context$contents[extra_lines], collapse = "")
154+
space_removed <- ee_space_removed(text = context$contents[line], cursor = cursor)
155+
new_cursor <- nchar(previous_len) + cursor - space_removed
156+
ee_get_funname(text = text_merge, cursor = new_cursor)
157+
} else {
158+
ee_get_funname(text = context$contents[line], cursor = cursor)
159+
}
160+
}

R/ee_Initialize.R

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,10 @@ ee_Initialize <- function(email = NULL,
259259
}
260260

261261
# Root folder exist?
262-
ee_user_assetroot <- try(ee$data$getAssetRoots()[[1]])
262+
ee_user_assetroot <- ee$data$getAssetRoots()
263+
assetroot_exist <- length(ee_user_assetroot) == 0
263264
# if ee_asset_home (list) length is zero
264-
if (length(ee_user_assetroot) == 0 | class(ee_user_assetroot) == "try-error") {
265+
if (assetroot_exist) {
265266
root_text <- paste(
266267
"Earth Engine Assets home root folder does not exist for the current user.",
267268
"Please enter your desired root folder name below. Take into consideration",
@@ -275,10 +276,10 @@ ee_Initialize <- function(email = NULL,
275276
)
276277
message(root_text)
277278
ee_createAssetHome()
278-
ee_user_assetroot <- ee$data$getAssetRoots()[[1]]
279+
ee_user_assetroot <- ee$data$getAssetRoots()
279280
}
280-
281-
ee_user <- ee_remove_project_chr(ee_user_assetroot$id)
281+
ee_user_assetroot_id <- ee_user_assetroot[[1]]$id
282+
ee_user <- ee_remove_project_chr(ee_user_assetroot_id)
282283

283284
options(rgee.ee_user = ee_user)
284285
ee_sessioninfo(
@@ -375,16 +376,17 @@ ee_create_credentials_drive <- function(email) {
375376
call. = FALSE
376377
)
377378
}
378-
# setting drive folder
379+
# Set folder to save Google Drive Credentials
379380
oauth_func_path <- system.file("python/ee_utils.py", package = "rgee")
380381
utils_py <- ee_source_python(oauth_func_path)
381382
ee_path <- ee_utils_py_to_r(utils_py$ee_path())
382383
email_clean <- gsub("@gmail.com", "", email)
383384
ee_path_user <- sprintf("%s/%s", ee_path, email_clean)
384-
# drive_credentials
385+
386+
# Load GD credentials (googledrive::drive_auth)
385387
repeat {
386388
full_credentials <- list.files(path = ee_path_user, full.names = TRUE)
387-
drive_condition <- grepl("@gmail.com", full_credentials)
389+
drive_condition <- grepl(".*_.*@.*", basename(full_credentials))
388390
if (!any(drive_condition)) {
389391
suppressMessages(
390392
googledrive::drive_auth(
@@ -404,8 +406,12 @@ ee_create_credentials_drive <- function(email) {
404406
break
405407
}
406408
}
407-
# from user folder to EE folder
408-
unlink(list.files(ee_path, "@gmail.com", full.names = TRUE))
409+
410+
# Clean previous and copy new GD credentials in ./earthengine folder
411+
clean_drive <- list.files(ee_path, ".*_.*@.*", full.names = TRUE) %in% list.dirs(ee_path)
412+
unlink(
413+
list.files(ee_path, ".*_.*@.*", full.names = TRUE)[!clean_drive]
414+
)
409415
file.copy(
410416
from = drive_credentials,
411417
to = sprintf("%s/%s", ee_path, basename(drive_credentials)),

R/ee_as_sf.R

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#' @param x Earth Engine table (ee$FeatureCollection) to be converted into a sf
44
#' object.
55
#' @param dsn Character. Output filename; in case \code{dsn} is missing
6-
#' \code{ee_as_sf} will create a temporary file.
6+
#' \code{ee_as_sf} will create a shapefile file in tmp() directory.
77
#' @param crs Integer or character. coordinate reference system
88
#' for the EE table. If is NULL, \code{ee_as_sf} will take the CRS of
99
#' the first element.
@@ -101,7 +101,7 @@ ee_as_sf <- function(x,
101101
sp_eeobjects <- ee_get_spatial_objects('Table')
102102

103103
if (missing(dsn)) {
104-
dsn <- paste0(tempfile(),".geojson")
104+
dsn <- paste0(tempfile(),".shp")
105105
}
106106

107107
if (!any(class(x) %in% sp_eeobjects)) {
@@ -195,12 +195,21 @@ ee_as_sf <- function(x,
195195
file_name <- paste0(table_id, "_", time_format)
196196

197197
# table to drive
198+
table_format <- ee_get_table_format(dsn)
199+
if (is.na(table_format)) {
200+
stop(
201+
'sf_as_ee(..., via = \"drive\"), only support the ',
202+
'following output format: "CSV", "GeoJSON", "KML", "KMZ", "SHP"',
203+
'. Use ee_table_to_drive and ee_drive_to_local to save in a TFRecord format.'
204+
)
205+
}
206+
198207
table_task <- ee_table_to_drive(
199208
collection = x_fc,
200209
description = ee_description,
201210
folder = container,
202211
fileNamePrefix = file_name,
203-
fileFormat = "GeoJSON",
212+
fileFormat = table_format,
204213
selectors = selectors
205214
)
206215

@@ -227,7 +236,12 @@ ee_as_sf <- function(x,
227236
overwrite = overwrite,
228237
consider = 'all'
229238
)
230-
local_sf <- sf::read_sf(dsn, quiet = TRUE)
239+
240+
if (table_format == "CSV") {
241+
return(read.csv(dsn, stringsAsFactors = FALSE))
242+
} else {
243+
local_sf <- sf::read_sf(dsn, quiet = TRUE)
244+
}
231245
} else if (via == 'gcs') {
232246
# Creating name for temporal file; just for either drive or gcs
233247
time_format <- format(Sys.time(), "%Y-%m-%d-%H:%M:%S")
@@ -245,13 +259,22 @@ ee_as_sf <- function(x,
245259

246260
file_name <- paste0(table_id, "_", time_format)
247261

248-
# table to drive
262+
# table to gcs
263+
table_format <- ee_get_table_format(dsn)
264+
if (is.na(table_format)) {
265+
stop(
266+
'sf_as_ee(..., via = \"gcs\"), only support the ',
267+
'following output format: "CSV", "GeoJSON", "KML", "KMZ", "SHP"',
268+
'. Use ee_table_to_drive and ee_drive_to_local to save in a TFRecord format.'
269+
)
270+
}
271+
249272
table_task <- ee_table_to_gcs(
250273
collection = x_fc,
251274
description = ee_description,
252275
bucket = container,
253276
fileNamePrefix = file_name,
254-
fileFormat = "GeoJSON",
277+
fileFormat = table_format,
255278
selectors = selectors
256279
)
257280

@@ -271,7 +294,11 @@ ee_as_sf <- function(x,
271294
stop(table_task$status()$error_message)
272295
}
273296
ee_gcs_to_local(task = table_task,dsn = dsn, overwrite = overwrite)
274-
local_sf <- sf::read_sf(dsn, quiet = TRUE)
297+
if (table_format == "CSV") {
298+
return(read.csv(dsn, stringsAsFactors = FALSE))
299+
} else {
300+
local_sf <- sf::read_sf(dsn, quiet = TRUE)
301+
}
275302
} else {
276303
stop("via argument invalid.")
277304
}
@@ -313,7 +340,32 @@ ee_fc_to_sf_getInfo <- function(x_fc, dsn, maxFeatures, overwrite = TRUE) {
313340
if (missing(dsn)) {
314341
x_sf
315342
} else {
316-
sf::write_sf(x_sf, dsn, delete_dsn = overwrite, quiet = TRUE)
343+
suppressWarnings(
344+
sf::write_sf(x_sf, dsn, delete_dsn = overwrite, quiet = TRUE)
345+
)
317346
x_sf
318347
}
319348
}
349+
350+
#' Sync sf and ee drivers
351+
#' @noRd
352+
ee_get_table_format <- function(dsn) {
353+
table_format <- tolower(sub(".*([.*])", "\\1", basename(dsn)))
354+
if (length(table_format) != 1) {
355+
stop("dns must be a single-length character")
356+
}
357+
358+
if (table_format == ".shp") {
359+
"SHP"
360+
} else if (table_format == ".geojson") {
361+
"GeoJSON"
362+
} else if (table_format == ".kml") {
363+
"KML"
364+
} else if (table_format == ".kmz") {
365+
"KMZ"
366+
} else if (table_format == ".csv") {
367+
"CSV"
368+
} else {
369+
NA
370+
}
371+
}

0 commit comments

Comments
 (0)