---
title: "Considerations"
output:
  html_document:
    toc: true
    toc_float:
      collapsed: false
      smooth_scroll: false
    toc_depth: 2
vignette: >
  %\VignetteIndexEntry{2. Considerations}
  %\VignetteEncoding{UTF-8}
  %\VignetteEngine{knitr::rmarkdown}    
---

Thanks to **reticulate** is it possible to embed a Python session within an R session. The **[Earth Engine Python API](https://pypi.org/project/earthengine-api/)** and **rgee** share the **same modules, classes, functions, and methods**. In other words, the logic of the syntax is the same and just as fast (just change **.** by a **$**). Notwithstanding, differences in the language design of R and Python might cause some problems in specific scenarios. We identify **four** bug-potential cases. Each of them is explained in-depth below.


```{r, setup, include=FALSE}
knitr::opts_chunk$set(
  comment = '', fig.width = 6, fig.height = 6
)
```

### **1. The map message error:**

This issue happens when the **map** method is used while: (1) running a reticulate version
lower than &lt; 1.14 (please update it!); or (2) leading
with **ee$List** objects. For instance:

``` r
library(rgee)
ee$Initialize()
mylist = ee$List$sequence(10)
mylist$map(function(x) ee$Number(x)$add(1))
#> Error in py_call_impl(callable, dots$args, dots$keywords): RuntimeError: Evaluation error: argument "x" is missing, with no default.
#> 
#> Detailed traceback: 
#>   File "/home/aybarpc01/.virtualenvs/r-reticulate/lib/python3.7/site-packages/ee/apifunction.py", line 205, in <lambda>
#>     return lambda *args, **kwargs: func.call(*args, **kwargs)  # pylint: disable=unnecessary-lambda
#>   File "/home/aybarpc01/.virtualenvs/r-reticulate/lib/python3.7/site-packages/ee/function.py", line 67, in call
#>     return self.apply(self.nameArgs(args, kwargs))
#>   File "/home/aybarpc01/.virtualenvs/r-reticulate/lib/python3.7/site-packages/ee/function.py", line 80, in apply
#>     result = computedobject.ComputedObject(self, self.promoteArgs(named_args))
#>   File "/home/aybarpc01/.virtualenvs/r-reticulate/lib/python3.7/site-packages/ee/function.py", line 107, in promoteArgs
#>     promoted_args[name] = Function._promoter(args[name], spec['type'])
#>   File "/home/aybarpc01/.virtualenvs/r-reticulate/lib/python3.7/site-packages/ee/__init__.py", line 242, in _Promote
#>     return CustomFunction.create(arg, 'Object', ['Object'] * args_count)
#>   File "/home/aybarpc01/.virtualenvs/r-reticulate/lib/python3.7/site-packages/ee/customfunction.py", line 121, in create
#>     return CustomFunction(signature, func)
#>   File "/home/aybarpc01/.virtualenvs/r-reticulate/lib/python3.7/site-packages/ee/customfunction.py", line 47, in __init__
#>     self._body = body(*variables)
#>   File "/home/aybarpc01/R/x86_64-pc-linux-gnu-library/3.6/reticulate/python/rpytools/call.py", line 21, in python_function
#>     raise RuntimeError(res[kErrorKey])
```

The code before is perfectly valid but `rgee` will produce an error.
This problem should be easily solved by adding the function **ee_utils_pyfunc**.
It will permit to wrap R functions before to send it to `reticulate`. Let’s see:

``` r
library(rgee)
ee$Initialize()
mylist = ee$List$sequence(0,10)
mynewlist = mylist$map(
  ee_utils_pyfunc(
    function(x) ee$Number(x)$add(1)   
  )
)
mynewlist$getInfo()
#>  [1]  1  2  3  4  5  6  7  8  9 10 11
```

### **2. Do not forget the L**

By default, when you define a number in R it will produce a **double
precision** value. This does not happen in Python because, by default it
will create an **int** value.

**Python**

``` python
type(1)
#> <class 'int'>
```

**R**

``` r
class(1)
#> [1] "numeric"
```

But why does this matter? Let's explain with an example:

**Python**

``` python
ee.Initialize()
and_bitwise = ee.Number(32).bitwiseAnd(100)
and_bitwise.getInfo()
#> 32
```

**R**

``` r
and_bitwise = ee$Number(32)$bitwiseAnd(100) #caution: silent error
and_bitwise$getInfo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/aybarpc01/.local/lib/python3.7/site-packages/ee/computedobject.py", line 95, in getInfo
    return data.computeValue(self)
  File "/home/aybarpc01/.local/lib/python3.7/site-packages/ee/data.py", line 490, in computeValue
    return send_('/value', ({'json': obj.serialize(), 'json_format': 'v2'}))
  File "/home/aybarpc01/.local/lib/python3.7/site-packages/ee/data.py", line 1186, in send_
    raise ee_exception.EEException(json_content['error']['message'])
ee.ee_exception.EEException: Number.bitwiseAnd: Bitwise operands must be integer only.
```

Users need to take into consideration that most of the arguments of the
Earth Engine methods are strict to admit only **integer values**. The
creation of integers in R is quite simple; you just need to add the
letter **L** to the end of the specific number or employ the
function `as.integer`. The **correct code** in R would be:

``` r
and_bitwise = ee$Number(32L)$bitwiseAnd(100L)
and_bitwise$getInfo()
#> [1] 32
```

### **3. Be careful with ee$Date**

This problem also appears due to differences between the design of R and
Python as programming languages. Currently, R only supports integer data 
type of 32 bits. Such integers can only count up to about 2 billion. Unfortunately, 
this range is insufficient to deal with [Google Earth
Engine timestamp](https://developers.google.com/earth-engine/glossary/)
which is saved in milliseconds since the [UNIX epoch](https://en.wikipedia.org/wiki/Unix_time).

**Python**

``` python
my_date = ee.Date('1990-01-01')
my_date.getInfo()
#> {'type': 'Date', 'value': 631152000000} # greater than 2 billion
```

**R**

``` r
my_date <- ee$Date('1990-01-01')
my_date$getInfo()
#> $type
#> [1] "Date"
#> 
#> $value
#> [1] -208192512
```

The problems with `ee$Date` just appear in the last mile (Python to R or
vice-versa, `reticulate`), and they should not be too severe if treated
with care. `rgee` implements two functions to deal with Earth Engine
dates: `eedate_to_rdate` and `rdate_to_eedate`.

``` r
# Era5 dataset
era_img <- ee$ImageCollection("ECMWF/ERA5/DAILY")$
  filterDate("2019-01-01", "2019-12-31")$
  first()
# Extracting init date
ee_date <- era_img$get('system:time_start')
ee_date$getInfo() # Silent error
#> [1] 112573440
eedate_to_rdate(ee_date = ee_date, timestamp = TRUE)
#> [1] 1.546301e+12
```

### **4. Take into consideration reserved words in R**

A reserved word is a word that cannot be used as an identifier, such as the name
of a variable or a function. According with `?reserved`, the reserved words in R's parser
are: `if`, `else`, **`repeat`**, `while`, `function`, `for`, `in`, `next`, `break`, `TRUE`, `FALSE`, `NULL`,
`Inf`, `NaN`, `NA`, `NA_integer_`, `NA_real_`, `NA_complex_`, `NA_character_`. Of these words,
the only one that is part of the Earth Engine API is **repeat**.

We can find **repeat** as a
method for an Earth Engine List object. See **[`ee$List$repeat(value, count)`](https://developers.google.com/earth-engine/apidocs/ee-list-repeat)**:

``` r
library(rgee)
ee_Initialize()
ee_list <- ee$List(1:10)
ee_list$repeat(10,2)$getInfo()
#> Error: unexpected 'repeat' in "ee_list$repeat"
```

To avoid this error use backticks/quotation marks:

``` r
library(rgee)
ee_Initialize()
ee_list <- ee$List(1:10)
ee_list$'repeat'(10,2)$getInfo()
#> 10 10
```
