Cliente x servidor

As bibliotecas de cliente do Earth Engine para Python e JavaScript convertem análises geoespaciais complexas em solicitações do Earth Engine. O código que você escreve para uma biblioteca de cliente pode conter uma mistura de referências a objetos e variáveis do lado do cliente que representam objetos do lado do servidor.

É importante distinguir os objetos do Earth Engine de outros objetos Python ou JavaScript ou primitivos que possam estar no seu código. É possível manipular objetos no servidor manipulando objetos "proxy" do lado do cliente no script. É possível reconhecer um objeto proxy como qualquer coisa que comece com ee. Esses objetos proxy do Earth Engine não contêm dados reais e são apenas identificadores de objetos no servidor. Para começar, considere um objeto de string do lado do cliente (que NÃO é um objeto proxy):

Editor de código (JavaScript)

var clientString = 'I am a String';
print(typeof clientString);  // string

Configuração do Python

Consulte a página Ambiente Python para informações sobre a API Python e o uso de geemap para desenvolvimento interativo.

import ee
import geemap.core as geemap

Colab (Python)

client_string = 'I am a String'
print(type(client_string))  # str

Observe na saída que o cliente (o navegador da Web ou o notebook) interpretou e executou esse código, determinando que a variável é do tipo string. Agora suponha que você quer que o Earth Engine faça algo com essa string. Para fazer isso, você precisa agrupar a string em um contêiner e enviá-la ao Google. Esse contêiner é o objeto proxy. Veja um exemplo:

Editor de código (JavaScript)

var serverString = ee.String('I am not a String!');
print(typeof serverString);  // object
print('Is this an EE object?',
    serverString instanceof ee.ComputedObject);  // true

Configuração do Python

Consulte a página Ambiente Python para informações sobre a API Python e o uso de geemap para desenvolvimento interativo.

import ee
import geemap.core as geemap

Colab (Python)

server_string = ee.String('I am not a String!')
print(type(server_string))  # ee.ee_string.String
print(
    'Is this an EE object?', isinstance(server_string, ee.ee_string.String)
)  # True

Observe na saída que ee.String é um object, e não um string. Mais especificamente, é um ee.computedObject, o que significa que é um objeto proxy de algo no servidor. Pense em ee.Thing como a maneira de colocar algo em um contêiner para enviar ao Google. Seu cliente não sabe o que está no contêiner, mas você pode descobrir imprimindo-o:

Editor de código (JavaScript)

print(serverString);  // I am not a String

Configuração do Python

Consulte a página Ambiente Python para informações sobre a API Python e o uso de geemap para desenvolvimento interativo.

import ee
import geemap.core as geemap

Colab (Python)

print(server_string.getInfo())  # I am not a String

Para conferir como o contêiner é, imprima a representação de string do objeto:

Editor de código (JavaScript)

print(serverString.toString());  // ee.String("I am not a String!")

Configuração do Python

Consulte a página Ambiente Python para informações sobre a API Python e o uso de geemap para desenvolvimento interativo.

import ee
import geemap.core as geemap

Colab (Python)

print(server_string)  # ee.String({"constantValue": "I am not a String!"})

Se, por algum motivo, você precisar usar Python ou JavaScript em execução no cliente para manipular o que estiver no contêiner, use getInfo() para extrair o conteúdo do contêiner e atribuir a uma variável:

Editor de código (JavaScript)

var someString = serverString.getInfo();
var strings = someString + '  Am I?';
print(strings);  // I am not a String!  Am I?

Configuração do Python

Consulte a página Ambiente Python para informações sobre a API Python e o uso de geemap para desenvolvimento interativo.

import ee
import geemap.core as geemap

Colab (Python)

some_string = server_string.getInfo()
strings = some_string + '  Am I?'
print(strings)  # I am not a String!  Am I?

Looping

Como o cliente não sabe o que está nos objetos ee.Thing do lado do servidor, as operações do lado do cliente, como condicionais e loops for, não funcionam com eles. Por esse motivo, e para evitar chamadas síncronas para getInfo(), use funções do servidor sempre que possível. Por exemplo, considere as duas maneiras a seguir de criar uma lista:

Não recomendado: loop for do lado do cliente

Editor de código (JavaScript)

var clientList = [];
for(var i = 0; i < 8; i++) {
  clientList.push(i + 1);
}
print(clientList);

Configuração do Python

Consulte a página Ambiente Python para informações sobre a API Python e o uso de geemap para desenvolvimento interativo.

import ee
import geemap.core as geemap

Colab (Python)

client_list = []
for i in range(8):
  client_list.append(i + 1)
print(client_list)

Recomendado: mapeamento do servidor

Editor de código (JavaScript)

var serverList = ee.List.sequence(0, 7);
serverList = serverList.map(function(n) {
  return ee.Number(n).add(1);
});
print(serverList);

Configuração do Python

Consulte a página Ambiente Python para informações sobre a API Python e o uso de geemap para desenvolvimento interativo.

import ee
import geemap.core as geemap

Colab (Python)

server_list = ee.List.sequence(0, 7)
server_list = server_list.map(lambda n: ee.Number(n).add(1))
print(server_list.getInfo())

O exemplo de mapeamento no servidor é um pouco, porque você pode criar a mesma lista simplesmente com ee.List.sequence(1, 8), mas ele ilustra alguns conceitos importantes. O primeiro conceito é map(), que simplesmente aplica a mesma função a tudo na lista. Como essa função é executada no servidor, as funções do lado do cliente, como getInfo() e print(), não vão funcionar em uma função mapeada. Por esse motivo, o código i + 1 precisa ser substituído pelo código equivalente do lado do servidor: ee.Number(n).add(1). É importante ressaltar que n é um objeto que existe apenas no servidor. Como a função não sabe o tipo do argumento, ela precisa ser convertida em ee.Number.

Consulte a seção sobre funções de cliente e servidor para uma descrição das funções executadas no cliente.

Vale lembrar que, às vezes, a funcionalidade do lado do cliente é conveniente. Por exemplo, o laço for anterior pode ser usado para criar uma lista e envolvê-la com um objeto do lado do servidor:

Editor de código (JavaScript)

var toServerList = ee.List(clientList);

Configuração do Python

Consulte a página Ambiente Python para informações sobre a API Python e o uso de geemap para desenvolvimento interativo.

import ee
import geemap.core as geemap

Colab (Python)

to_server_list = ee.List(client_list)

O processamento do lado do cliente é feito no seu notebook ou navegador, na CPU da máquina host, e pode ser menos eficiente do que usar o Earth Engine para fazer o trabalho no servidor. Além disso, para evitar resultados potencialmente surpreendentes, é recomendável não misturar a funcionalidade do cliente e do servidor nos scripts. A seção Condições mostra um exemplo de consequências não intencionais.

Condicionais

Os objetos do lado do servidor não necessariamente funcionam com funções do lado do cliente e vice-versa. Por exemplo, considere o caso de uma variável booleana do lado do servidor:

Editor de código (JavaScript)

var myList = ee.List([1, 2, 3]);
var serverBoolean = myList.contains(5);
print(serverBoolean);  // false

Configuração do Python

Consulte a página Ambiente Python para informações sobre a API Python e o uso de geemap para desenvolvimento interativo.

import ee
import geemap.core as geemap

Colab (Python)

my_list = ee.List([1, 2, 3])
server_boolean = my_list.contains(5)
print(server_boolean.getInfo())  # False

Como mostrado no exemplo abaixo, a variável não se comporta em uma condicional do lado do cliente porque é um objeto do lado do servidor. Para verificar corretamente um booleano do lado do servidor, use uma função do lado do servidor:

Não recomendado: condicional do lado do cliente

Editor de código (JavaScript)

var clientConditional;
if (serverBoolean) {
  clientConditional = true;
} else {
  clientConditional = false;
}
print('Should be false:', clientConditional);  // True!

Configuração do Python

Consulte a página Ambiente Python para informações sobre a API Python e o uso de geemap para desenvolvimento interativo.

import ee
import geemap.core as geemap

Colab (Python)

if server_boolean:
  client_conditional = True
else:
  client_conditional = False
print('Should be False:', client_conditional)  # True!

Recomendado: condicional do lado do servidor

Editor de código (JavaScript)

var serverConditional = ee.Algorithms.If(serverBoolean, 'True!', 'False!');
print('Should be false:', serverConditional);  // False!

Configuração do Python

Consulte a página Ambiente Python para informações sobre a API Python e o uso de geemap para desenvolvimento interativo.

import ee
import geemap.core as geemap

Colab (Python)

server_conditional = ee.Algorithms.If(server_boolean, 'True!', 'False!')
print('Should be False:', server_conditional.getInfo())  # False!

Funções de cliente e servidor

As seções anteriores descrevem vários motivos pelos quais é ineficiente ou ilógico misturar objetos e funções de cliente e servidor. Quais objetos e funções são do lado do cliente e do lado do servidor? Em geral, qualquer coisa inicializada como ee.Thing é um objeto de servidor, e qualquer método nesse objeto, ee.Thing.method(), é uma função do servidor. Os objetos e as funções que aparecem na referência do Python ou do JavaScript são do lado do cliente. Conforme observado anteriormente, é possível usar a funcionalidade do lado do cliente para criar um objeto e, em seguida, agrupá-lo fornecendo o objeto do lado do cliente para um construtor do Earth Engine, por exemplo, ee.String().