若い頃は新しいソフトウェアの操作をすぐに覚えたけれど、
歳をとると、操作方法を覚えるのは一苦労である…。
その点、RやGEEは操作方法を覚える必要が無いので良い。
しかしながら、慣れれば、慣れるほど、
同じコードを書くのが面倒になってくる。
できれば、コードの再利用をしてみたくなる。
例えば、カラーパレットの定義やUIなどを毎回作るのは面倒である。
そこで、今回はよく使う機能をモジュール化し、
再利用するための方法を検討する。
上手く使いこなすことができれば生産性も向上すると期待できる。
まず、分析用のモジュールを格納するためのレポジトリを用意する。
Scripts タブの NEW をクリックし、オブジェクトの新規 メニューを開き、
Repository を選択する。
レポジトリの名前は何でも良いけれど、今回は「modules」にしておく。
すると、Scripts タブに新しいレポジトリが登録される。
今回はこのレポジトリの中に二つのプログラムを登録することにする。
まずは、可視化パラメータを作ってみる。
新規ファイルを作成し、以下の内容を貼り付ける。
コードはカラーパレットやLandsatの可視化パラメータである。
貼り付けたら「visParam」という名前で作ったレポジトリに保存する。
exports.veg = ['blue', 'red', 'yellow', 'green'];
exports.dem = ['green', 'yellow', 'orange', 'brown', 'white'];
exports.rb = ['red', 'white', 'blue'];
exports.br = ['blue', 'white', 'red'];
exports.ro = ['red', 'yellow', 'orange'];
exports.Ln5TOA = {
bands: ['B3_median', 'B2_median', 'B1_median'],
gamma: 1,
max: 0.2,
min: 0.0
};
exports.Ln8TOA = {
bands: ['B4_median', 'B3_median', 'B2_median'],
gamma: 1,
max: 0.2,
min: 0.0
};
exports.dem = ['green', 'yellow', 'orange', 'brown', 'white'];
exports.rb = ['red', 'white', 'blue'];
exports.br = ['blue', 'white', 'red'];
exports.ro = ['red', 'yellow', 'orange'];
exports.Ln5TOA = {
bands: ['B3_median', 'B2_median', 'B1_median'],
gamma: 1,
max: 0.2,
min: 0.0
};
exports.Ln8TOA = {
bands: ['B4_median', 'B3_median', 'B2_median'],
gamma: 1,
max: 0.2,
min: 0.0
};
これまでのは「var」によって変数を宣言していたが、
上記のコードでは変数の前に「exports.」が付いている。
この魔法の言葉をつけることで外部から関数や変数を呼び出すことできる。
ついでに、MapLinkerを作成するコードについてもモジュール化してみる。
新規ファイルを作成、以下のコードを貼り付ける。
中身の処理については以前の内容を参照。
今回作成する関数「mapLinker()」は左右に画像を並べて表示するプログラムであり、
画像オブジェクト(left と right)、可視化パラメータ(l_visParam と r_visParam)、
および、表示用のラベル名(l_label と r_label)の6つを引数とする。
exports.mapLinker = function(
left, right, l_visParam, r_visParam, l_label, r_label) {
// 複数のマップオブジェクトを格納するための空の配列を定義する。
var maps = [];
// マップ領域を準備する。
var map_left = ui.Map(); // 左側のマップ領域
var map_right = ui.Map(); // 右側のマップ領域
// それぞれのレイヤにそれぞれの画像を追加する。
map_left.addLayer(left, l_visParam, l_label);
map_right.addLayer(right, r_visParam, r_label);
// それぞれのMapにタイトルラベルを追加する。
map_left.add(ui.Label(l_label));
map_right.add(ui.Label(r_label));
// それぞれのMapにレイヤー・マネージャーを追加する。
map_left.setControlVisibility(true);
map_right.setControlVisibility(true);
// それぞれのMapを配列に追加する。
maps.push(map_left);
maps.push(map_right);
// マップ・リンカーオブジェクトを作って、複数のマップを連動させる
var linker = ui.Map.Linker(maps);
// UIをリセットする。
ui.root.widgets().reset(maps);
// 地図の中心をひとつ目のマップのオブジェクトの衛星画像に設定する。
maps[0].centerObject(map_left, 9);
};
left, right, l_visParam, r_visParam, l_label, r_label) {
// 複数のマップオブジェクトを格納するための空の配列を定義する。
var maps = [];
// マップ領域を準備する。
var map_left = ui.Map(); // 左側のマップ領域
var map_right = ui.Map(); // 右側のマップ領域
// それぞれのレイヤにそれぞれの画像を追加する。
map_left.addLayer(left, l_visParam, l_label);
map_right.addLayer(right, r_visParam, r_label);
// それぞれのMapにタイトルラベルを追加する。
map_left.add(ui.Label(l_label));
map_right.add(ui.Label(r_label));
// それぞれのMapにレイヤー・マネージャーを追加する。
map_left.setControlVisibility(true);
map_right.setControlVisibility(true);
// それぞれのMapを配列に追加する。
maps.push(map_left);
maps.push(map_right);
// マップ・リンカーオブジェクトを作って、複数のマップを連動させる
var linker = ui.Map.Linker(maps);
// UIをリセットする。
ui.root.widgets().reset(maps);
// 地図の中心をひとつ目のマップのオブジェクトの衛星画像に設定する。
maps[0].centerObject(map_left, 9);
};
このように「customUi」と「visParam」の二つのモジュールを準備する。
これらのモジュールの準備ができたら、次に、これらを実行するプログラムを準備する。
とりあえず、Landsat 5 と Landsat 8 の画像(Tier 1 TOA Reflectance)を検索し、
それぞれ、「landsat5」と「landsat8」という名前でインポートする。
その上で、以下のコードを貼りけて実行する。
// 外部ライブラリを読み込む
var customUi = require('users/yufujimoto/modules:customUi');
var visParam = require('users/yufujimoto/modules:visParam');
var customUi = require('users/yufujimoto/modules:customUi');
var visParam = require('users/yufujimoto/modules:visParam');
// Landsat 5 の画像を読み込む。
var ln5 = ee.ImageCollection(landsat5
.filterDate("1989-01-01","1990-12-31")
.filterMetadata("CLOUD_COVER","not_greater_than",10)
);
// Landsat 8 の画像を読み込む。
var ln8 = ee.ImageCollection(landsat8
.filterDate("2016-01-01","2017-12-31")
.filterMetadata("CLOUD_COVER","not_greater_than",10)
);
// シンプルコンポジットを作成する。
var ln5_sc = ln5.reduce(ee.Reducer.median());
var ln8_sc = ln8.reduce(ee.Reducer.median());
// 作成した外部モジュールを使ってMapLinkerを作成する。
customUi.mapLinker(
ln5_sc, ln8_sc,
visParam.Ln5TOA, visParam.Ln8TOA,
"1989-1990", "2016-2017"
);
customUi.mapLinker(
ln5_sc, ln8_sc,
visParam.Ln5TOA, visParam.Ln8TOA,
"1989-1990", "2016-2017"
);
ここで重要となるのが最初の二行と最後の一行の部分である。
すなわち、require() 関数によって読み込んでインスタンス化し、
すなわち、require() 関数によって読み込んでインスタンス化し、
インスタン化されたオブジェクトを通して実行する。
すなわち、可視化パラメータに関しては visParamという名前でインスタンス化し、
visParam.Ln5TOA と visParam.Ln8TOA としてモジュールで定義した変数を呼び出す。
同様に、customUi.mapLinker() によって独自に定義した関数を呼び出している。
すなわち、可視化パラメータに関しては visParamという名前でインスタンス化し、
visParam.Ln5TOA と visParam.Ln8TOA としてモジュールで定義した変数を呼び出す。
同様に、customUi.mapLinker() によって独自に定義した関数を呼び出している。
実行した結果は以下の通り。モジュール化によってコードが見やすくなった。
https://code.earthengine.google.com/7af5f2f2c055afdb383d3ec9f297bf38
This work is licensed under a Creative Commons Attribution 4.0 International License.
0 件のコメント:
コメントを投稿