クライアントとサーバー

PythonJavaScript 用の Earth Engine クライアント ライブラリは、複雑な地理空間分析を Earth Engine リクエストに変換します。クライアント ライブラリ用に作成するコードには、クライアントサイド オブジェクトへの参照と、サーバーサイド オブジェクトを表す変数が混在している場合があります。

Earth Engine オブジェクトは、コードに含まれる可能性がある他の Python オブジェクトや JavaScript オブジェクト、プリミティブと区別することが重要です。スクリプトでクライアントサイドの「プロキシ」オブジェクトを操作することで、サーバー上のオブジェクトを操作できます。プロキシ オブジェクトは、ee で始まる任意のオブジェクトとして認識できます。これらの Earth Engine プロキシ オブジェクトには実際のデータは含まれず、サーバー上のオブジェクトのハンドルにすぎません。まず、クライアントサイドの文字列オブジェクト(プロキシ オブジェクトではない)について考えてみましょう。

コードエディタ(JavaScript)

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

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

import ee
import geemap.core as geemap

Colab(Python)

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

出力から、クライアント(ウェブブラウザまたはノートブック)がこのコードを解釈して実行し、変数が string 型であることを判断したことを確認します。この文字列で Earth Engine が何かを実行できるようにしたいとします。そのためには、文字列を適切なコンテナにラップして Google に送信する必要があります。このコンテナがプロキシ オブジェクトです。次の例をご覧ください。

コードエディタ(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

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

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

出力から、ee.Stringstring ではなく object であることがわかります。具体的には、ee.computedObject です。つまり、サーバー上の何かのプロキシ オブジェクトです。ee.Thing は、Google に送信するためにコンテナにアイテムを配置する方法と考えてください。クライアントはコンテナの内容を把握していませんが、印刷することで内容を確認できます。

コードエディタ(JavaScript)

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

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

import ee
import geemap.core as geemap

Colab(Python)

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

コンテナ自体の外観を確認するには、オブジェクトの文字列表現を出力します。

コードエディタ(JavaScript)

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

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

import ee
import geemap.core as geemap

Colab(Python)

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

なんらかの理由で、クライアントで実行されている Python または JavaScript を使用してコンテナ内のものを操作する必要がある場合は、getInfo() を使用してコンテナの内容を取得し、変数に割り当てます。

コードエディタ(JavaScript)

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

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

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?

ループ

クライアントはサーバーサイドの ee.Thing オブジェクトの内容を認識しないため、条件文や for ループなどのクライアントサイド オペレーションはサーバーサイド ee.Thing オブジェクトでは機能しません。そのため、getInfo() の同期呼び出しを回避するには、可能な限りサーバー関数を使用してください。たとえば、リストを作成する方法は次の 2 つです。

推奨されない - クライアントサイドの for ループ

コードエディタ(JavaScript)

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

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

import ee
import geemap.core as geemap

Colab(Python)

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

推奨 - サーバーサイド マッピング

コードエディタ(JavaScript)

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

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

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())

サーバーサイド マッピングの例は、ee.List.sequence(1, 8) で同じリストを簡単に作成できるため、少しばかげていますが、重要なコンセプトを説明しています。最初のコンセプトは map() です。これは、リスト内のすべての要素に同じ関数を適用するだけです。この関数はサーバー上で実行されるため、getInfo()print() などのクライアントサイド関数は、マッピングされた関数では機能しません。このため、i + 1 コードは同等のサーバーサイド コード ee.Number(n).add(1) に置き換える必要があります。重要なのは、n はサーバーにのみ存在するオブジェクトであるということです。この関数は引数の型を認識しないため、ee.Number にキャストする必要があります。

(クライアントで実行される関数の説明については、クライアントとサーバーの関数に関するセクションをご覧ください)。

クライアントサイドの機能が便利な場合もあります。たとえば、前の for ループを使用してリストを作成し、サーバーサイド オブジェクトでラップできます。

コードエディタ(JavaScript)

var toServerList = ee.List(clientList);

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

import ee
import geemap.core as geemap

Colab(Python)

to_server_list = ee.List(client_list)

クライアントサイド処理はノートブックまたはブラウザ(ホストマシンの CPU)で行われるため、Earth Engine を使用してサーバーで処理を行うよりも効率が低くなる可能性があります。また、予期しない結果を回避するため、スクリプトでクライアント機能とサーバー機能を混在させないようにすることをおすすめします。[条件] セクションでは、意図しない結果の例を示します。

条件

サーバーサイド オブジェクトがクライアントサイド関数と連携するとは限りません。また、その逆も同様です。たとえば、サーバーサイドのブール値変数の場合について考えてみましょう。

コードエディタ(JavaScript)

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

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

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

次の例に示すように、この変数はサーバーサイド オブジェクトであるため、クライアントサイドの条件付きで動作しません。サーバーサイドのブール値を正しく確認するには、サーバーサイド関数を使用します。

非推奨 - クライアントサイドの条件分岐

コードエディタ(JavaScript)

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

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

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!

推奨 - サーバーサイドの条件

コードエディタ(JavaScript)

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

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

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!

クライアントとサーバーの機能

前のセクションでは、クライアント オブジェクトとサーバー オブジェクト、およびクライアント関数とサーバー関数を混在させることが非効率的または非論理的である理由をいくつか説明しました。どのオブジェクトと関数がクライアントサイドで、どの関数がサーバーサイドですか?一般に、ee.Thing として初期化されたものはサーバー オブジェクトであり、そのオブジェクトのメソッド(ee.Thing.method())はサーバー関数です。Python または JavaScript のリファレンスに記載されているオブジェクトと関数はクライアントサイドです。前述のように、クライアントサイド機能を使用してオブジェクトを作成し、クライアントサイド オブジェクトを Earth Engine コンストラクタ(ee.String() など)に渡してラップできます。