This document was written in the transition phase between the openEO API versions 0.4.x and 1.0. Therefore we will use often terms that originate from the API version 0.4.x. We will try to modify this document as the 1.0 matures.
Some concept mappings:
|0.4.x|1.0.0| |-|-| |process graph|user defined process| |openEO process| predefined process| |callback / sub process graph |user defined process| |callback argument| process parameter| |variable| process graph parameter |
As with the openEO API versions 0.4.x we introduced the concept of callbacks which are used for processing data within processes. For example, if we modify a data cube by reducing it by its temporal dimension, we apply a specific function that defines how the mapping from a time series into a scalar is done. This and similarly functions that describe such mapping functions for reduce / apply or aggregate processes are called a callbacks.
Usually this behavior in R can be achieved by passing a function as parameter, e.g. the various apply
functions. In the openEO R client prior to 0.6.x callbacks had to be solely created as the openEO concept 'callback' by creating a sub graph and using the processes provided by the back-end. This will be still a viable option to do, if there are complex functions or if a particular back-end does not comply to the well defined common set of openEO processes.
For the client version >= 0.6 we wanted to mimic the R specific behavior better by allowing to pass a function as parameter which is evaluated into sub process graph / callback. A similar approach was achieved with the function band_arithmetics
which was available in the client version 0.5.0. For this purpose the function statement was evaluated and translated into a set of openEO process. This means basically that a process graph was created by mapping primitve R operators like +
or *
into the corresponding openEO processes. To evaluate the function we did not use R's internal call evaluation engine, but implemented an own approach, due to the fact that only a mapping was done and no real calculation.
However, this has limited the use and portability of this feature. Using the R call engine would make the feature protable and extensible. The challenge with this new approach was that we have to do the following:
ProcessNode
, Variable
and ProcessGraphParameter
ProcessGraphParameter
In the R client domain a ProcessGraphParameter
is the defined parameter in the signature of the callback function. In the API it was called callback-argument
in the versions < 1.0. In case of a temporal reduction the ProcessGraphParameter
would be a time series or to be more technically an array or in R terms a numeric vector, when the graph it evaluated for processing at the back-end. But for the R-client this will not hold any real value. It refers simply to the parameter that has to be used in this context. In order to create the process graph for the computations at the back-end.
We overloaded many of the primitive operators in R. The result of those functions are ProcessNode
's which are created by mapping the primitive functions to the equivalent openEO processes. This, however, requires back-ends to be fully compliant to the openEO processes in terms of those mathematical and logical operators. If the back-end is not compliant you can use the ProcessNodes
created by a ProcessCollection
from the processes()
.
Mapping:
|R primitive|openEO process| |-|-| |abs|"absolute" | |sign| "sgn" | | sqrt | "sqrt" | | trunc | "int" | | floor | "floor" | | ceiling | "ceil" | | round | "round" | | exp | "exp" | | log | "ln" if base = exp(1), "log10" if base = 10 or else "log" | | cos | "cos" | | sin | "sin" | | tan | "tan" | | cosh | "cosh" | | sinh | "sinh" | | tanh | "tanh" | | acos | "arccos" | | asin | "arcsin" | | atan | "arctan" | | acosh | "arccosh" | | asinh | "arcsinh" | | atanh | "arctanh" | | cumsum | "cumsum" | | cummin | "cummin" | | cummax | "cummax" | | cumprod | "cumprod" | | [ | "array_element" | | + | "add" | | - | "subtract" | | * | "multiply" | | / | "divide" | | ^ | "power" | | %% | "mod" | | ! | "not" | | && | "and" | | \|\| | "or" | | xor | "xor" | | == | "eq" | | != | "neq" | | < | "lt" | | <= | "lte" | | >= | "gte" | | > | "gt" | | sum | "sum" | | prod | "product" | | min | "min" | | max | "max" | | range | "extrema" | | mean | "mean" | | median | "median" | | sd | "sd" | | var | "var" | | quantile | "quantiles" |
con = connect(host = host,version=version,user=user,password=pwd,login_type = "basic") graph = process_graph_builder(con = con)
spectral_reduce = data %>% graph$reduce(dimension = "bands") evi_graph = con %>% callback(spectral_reduce,parameter = "reducer") nir = evi_graph$data$data %>% evi_graph$array_element(0) red = evi_graph$data$data %>% evi_graph$array_element(1) blue = evi_graph$data$data %>% evi_graph$array_element(2) p1 = evi_graph$product(data = list(red, 6)) p2 = evi_graph$product(data = list(blue, -7.5)) sub = evi_graph$subtract(data = list(nir,red)) sum = evi_graph$sum(data = list(1,nir,p1,p2)) div = evi_graph$divide(data = list(sub,sum)) p3 = evi_graph$product(data = list(2.5,div)) evi_graph$setFinalNode(p3)
evi_calculation = data %>% band_arithmetics(graph = graph,function(x) { 2.5*((x[1]-x[2])/sum(1,x[1],6*x[2],-7.5*x[3])) })
spectral_reduce = graph$reduce(data = data, dimension = "bands",reducer = function(x) { B08 = x[1] B04 = x[2] B02 = x[3] (2.5 * (B08 - B04)) / sum(B08, 6 * B04, -7.5 * B02, 1) })
con = connect(host = host,version=version,user=user,password=pwd,login_type = "basic") p = processes() spectral_reduce = p$reduce_dimension(data = data, dimension = "bands", reducer = function(data,context) { B08 = data[1] B04 = data[2] B02 = data[3] (2.5 * (B08 - B04)) / sum(B08, 6 * B04, -7.5 * B02, 1) })
Either of the following variations can be used:
con = connect(host = host,version=version,user=user,password=pwd,login_type = "basic") graph = process_graph_builder(con = con)
temporal_reduce = graph$reduce(data = spectral_reduce,dimension = "temporal", reducer = function(x) { min(x) })
temporal_reduce = graph$reduce(data=spectral_reduce,dimension = "temporal", reducer = graph$min)
temporal_reduce = graph$reduce(data=spectral_reduce,dimension = "temporal", reducer = min)
Starting with version 1.0.0 all reducer / aggregation functions are passed as function with specific parameters. Using the process constructor from the ProcessCollection
or R's aggregation functions are no longer supported due to continous mismatches between the provided process parameter of the ProcessArgument
and the process parameter definition of the reducer / aggregation function (often times there are context
parameter which causes problems with the unary operators). The other problem is that R's aggregation functions also follow another definition schema, so that it cannot reliably mapped, when passed on directly.
con = connect(host = host,version=version,user=user,password=pwd,login_type = "basic") p = processes()
temporal_reduce = p$reduce_dimension(data = spectral_reduce,dimension = "t", reducer = function(data, context) { min(data) })
x[1]
more than once would create multiple different ProcessNodes
with different process ids, which might lead to unwanted additional costs at the back-endAdd the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.