Python と JavaScript 用の Earth Engine クライアント ライブラリは、複雑な地理空間分析を Earth Engine リクエストに変換します。クライアント ライブラリ用に作成するコードには、クライアントサイド オブジェクトへの参照と、サーバーサイド オブジェクトを表す変数が混在している場合があります。
Earth Engine オブジェクトは、コードに含まれる可能性がある他の Python オブジェクトや JavaScript オブジェクト、プリミティブと区別することが重要です。スクリプトでクライアントサイドの「プロキシ」オブジェクトを操作することで、サーバー上のオブジェクトを操作できます。プロキシ オブジェクトは、ee
で始まる任意のオブジェクトとして認識できます。これらの Earth Engine プロキシ オブジェクトには実際のデータは含まれず、サーバー上のオブジェクトのハンドルにすぎません。まず、クライアントサイドの文字列オブジェクト(プロキシ オブジェクトではない)について考えてみましょう。
コードエディタ(JavaScript)
var clientString = 'I am a String'; print(typeof clientString); // string
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
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.String
が string
ではなく object
であることがわかります。具体的には、ee.computedObject
です。つまり、サーバー上の何かのプロキシ オブジェクトです。ee.Thing
は、Google に送信するためにコンテナにアイテムを配置する方法と考えてください。クライアントはコンテナの内容を把握していませんが、印刷することで内容を確認できます。
コードエディタ(JavaScript)
print(serverString); // I am not a String
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!")
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?
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);
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);
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);
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
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!
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!
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()
など)に渡してラップできます。