PythonでJAXAの人工衛星だいち(ALOS)の世界標高データ活用(1)

 For Not only Japan domein, but also global dataでTerrain AnalysisをActするべく、Geospatial Information Authority of Japan(国土地理院)のDEM_Dataから離れて、JAXAがDevelop&OperateしたArtificial Steliteのだいち(ALOS)がGetした高精度の全天球ElevationModelの活用についてLearningでございます。

(参考)JAXAのだいち(ALOS)に関する解説Page:https://www.satnavi.jaxa.jp/ja/project/alos/index.html

 だいち(ALOS)にはたくさんの機能があると、改めて思いますが、ここはSimpleにElevationDataの活用を目指します。このWebSiteはALOSをはじめとするJAXAのArtificialSteliteのIntroductionで、ALOSのVarius kind of DataをGettingは次のURLになります。

(参考)ALOS利用推進研究プロジェクトのURL:https://www.eorc.jaxa.jp/ALOS/jp/index_j.htm

 このPageにもいろいろなDataがexistしますが、今回は「全球高精度デジタル3D地図(ALOS_World_3D)」を活用させていただきます。このDataの概要は同Pageによると次のように解説されています。「「だいち」搭載光学センサPRISMを用いた全球陸域を対象とした高精度デジタル3D地図。水平解像度30m相当の全球数値標高モデル第3.2版を公開中。」

 ALOS_World_3DのURL(https://www.eorc.jaxa.jp/ALOS/jp/dataset/aw3d_j.htm)に移動すると、ProfessinalSpecの平面解像度5mVersionと、PublicSpec&FreeOfChargeの平面解像度30mVersionがIntroduceされています。今回はLearning&Practiceなので、PriceFreeの30mPressisionVersionをMakeUseします。このPageに「全球数値地表モデル (DSM) の30m解像度版データセット」へのリンク(https://www.eorc.jaxa.jp/ALOS/jp/dataset/aw3d30/aw3d30_j.htm)があるので、こちらに移動すると、Like BelowのGlobalMapが表示されます。

 LandRegionのAllOfAreaがColorDrawnなので、ver4.1までに全世界のElevationDataがBeAbleToCompleteのRecognitionです。すごいのが、Commercial or Non-Commercial問わずにFreeでAvailableというPointでございます。JAXAさまに大感謝でございます。

 わたくしはAmatureUserなので、早速、「4.データのダウンロード方法」と「ユーザー登録」しました。ユーザー登録は指示に従ってProcessすれば問題なく完了するはずです。

UserRegisterationが完了したら、早速データのダウンロード用のリンク先(https://www.eorc.jaxa.jp/ALOS/en/aw3d30/data/index.htm)に移動します。

 最初はPythonのコードから直接Download Siteにアクセスして、圧縮ファイルを取得しようとおもったのですが、UserIDとpassの入力が必要なためWeb scripingなどの操作が煩雑になるため、一度、必要な圧縮ファイルをダウンロードして、それをPythonCodeで解凍した方がよいとGemini先生に助言をいただいたので、その方法を採用しました。

 まずは手始めに中国、四国、九州地方を含む5✕5のTileをDownLoadします。

  話題が前後しますが、ALOSのTile座標の考え方をGemini先生に確認すると、おおむね以下のような回答をいただきました。

  • ALOSのTileの大きさは緯度1度、経度1度単位で設定
  • Tileの中の標高値は東西3600×南北3600個を格納
  • Tile中のPixel座標は東西・南北ともに緯度・経度と線形関係で設定(標高値の平面的感覚は緯度・経度ともに1秒ごとに設定されている)

 Pixel座標と緯度・経度の変換式は、具体的には別途学習したいと思いますが、Geospatial Information Authority of Japanのいわゆる地理院Tileと比較すると、複雑ではなさそうです。

 話題を戻して、先ほどのDataDownloadSiteに進み、ID/Passを入力すると次の画面が表示されました。

 このMap上でDownloadしたいRegionをLeftCrickしていくと、MapがEnlargeしていきます。数回LeftClickすると下のような画面になります。これが5×5のTileの一括Download画面になり、オレンジ色のDownloadButtonをClickすると、DataのDownloadが始まります。この画面(四国地方全域と、中国・九州地方の一部)のDataは「N030E130_N035E135.zip」というNameのZipFileでしたBottomLeftのTileの左上角部の座標が北緯30度・東経130度を、UpperRightの左上角部の座標が北緯35度・東経135度であることを表してるNameであると予想しました。


 ちなみに、この5×5のTileのいずれか1つのTileをClickすると、1つのTileのみをDownloadする以下のような画面にTransferします。
 おおむね準備が整いました。「N030E130_N035E135.zip」を解凍して、格納されている標高DataをShowPlotするPythonCodeをGemini先生のAdviceをいただきながら、Creatしていきます。

 下準備として、Downloadした「N030E130_N035E135.zip」をGoogleColabのTemporaryFolderにDrag&Dropして、Uploadします。

 そして、GoogleColabのPythonCodeで「N030E130_N035E135.zip」を読み込んで、解凍します。Gemini先生のOpusです。Gemini先生はtry-exceptを多用してCodeのVolumeを増やすくせがあるようで、最近少々困っています。
import zipfile
import os

# アップロードしたzipファイルのパス
zip_filepath = '/content/N030E130_N035E135.zip'

# 解凍先のベースディレクトリ
# この中に 'N030E130_N035E135' フォルダが作成され、GeoTIFFファイルが格納されます
extracted_base_dir = '/content/extracted_elevation_data'

# 解凍先の最終パスを生成 (zipファイル内のフォルダ構造を考慮)
# zipファイルが N030E130_N035E135 というフォルダを含んでいると仮定
final_extracted_data_dir = os.path.join(extracted_base_dir, 'N030E130_N035E135')

# 解凍先のディレクトリが存在しない場合は作成
os.makedirs(final_extracted_data_dir, exist_ok=True)

print(f"Zipファイル '{zip_filepath}' の解凍を開始します...")

try:
    with zipfile.ZipFile(zip_filepath, 'r') as zip_ref:
        # extractall() は、zipファイル内のトップレベルのフォルダ構造を維持して解凍します。
        # そのため、extracted_base_dir の中に N030E130_N035E135 フォルダが作成されます。
        zip_ref.extractall(extracted_base_dir)
    print(f"Zipファイルを '{extracted_base_dir}' に正常に解凍しました。")
    print(f"GeoTIFFファイルは '{final_extracted_data_dir}' の中に格納されています。")

except FileNotFoundError:
    print(f"エラー: Zipファイル '{zip_filepath}' が見つかりません。ファイル名とパスを確認してください。")
except zipfile.BadZipFile:
    print(f"エラー: '{zip_filepath}' は無効なzipファイルです。再ダウンロードを検討してください。")
except Exception as e:
    print(f"Zipファイルの解凍中に予期せぬエラーが発生しました: {e}")

 ZipFileの回答が成功すると、以下のようなMassegeが出力されます。
Zipファイル '/content/N030E130_N035E135.zip' の解凍を開始します... Zipファイルを '/content/extracted_elevation_data' に正常に解凍しました。 GeoTIFFファイルは '/content/extracted_elevation_data/N030E130_N035E135' の中に格納されています。

 スムーズにFileを解凍できた模様です。FileのA‗Part Of Contentsはこのようになっています。標高データは「…_DSM.tif」に格納されており、FileNameの後半のN030E130は当該TileのUpperRightCornerが北緯30度東経130度であることを表しています。

 最初に「ALPSMLC30_N031E130_DSM.tif」という1つのTileのElevationDataをMatplotlibを使ってContourをCreatしてみます。Gemini先生にCodeをお願いしました。

import rasterio
import matplotlib.pyplot as plt
import numpy as np

# TIFFファイルのパス
tif_file_path = '/content/extracted_elevation_data/N030E130_N035E135/ALPSMLC30_N031E130_DSM.tif'

print(f"TIFFファイル '{tif_file_path}' の読み込みを開始します...")

try:
    # rasterio を使ってTIFFファイルを読み込む
    with rasterio.open(tif_file_path) as src:
        # 標高データを読み込む (通常は1番目のバンド)
        elevation_data = src.read(1)

        # ファイルのメタデータから座標参照系 (CRS) や変換情報 (transform) を取得
        crs = src.crs
        transform = src.transform
        bounds = src.bounds

        print(f"ファイル名: {src.name}")
        print(f"幅 (pixels): {src.width}")
        print(f"高さ (pixels): {src.height}")
        print(f"バンド数: {src.count}")
        print(f"CRS (座標参照系): {crs}")
        print(f"バウンディングボックス (minx, miny, maxx, maxy): {bounds}")
        print(f"データ型: {elevation_data.dtype}")
        print(f"データ範囲 (min, max): {np.nanmin(elevation_data)}, {np.nanmax(elevation_data)}")

    print("データ読み込み完了。図化を開始します...")

    # Matplotlibで図化
    plt.figure(figsize=(10, 8)) # 図のサイズを設定

    # imshowを使ってデータを画像として表示
    # extent: データの地理的な範囲 (left, right, bottom, top)
    # cmap: カラーマップ (標高データには'terrain', 'viridis', 'gray'などがよく使われます)
    # origin='upper': 画像の原点を左上にする (地理空間データでは一般的)
    # interpolation='none': ピクセル補間なし (データがそのまま表示される)
    img_plot = plt.imshow(
        elevation_data,
        cmap='terrain', # 'viridis', 'gray', 'jet' なども試してみてください
        origin='upper',
        extent=[bounds.left, bounds.right, bounds.bottom, bounds.top]
    )

    # カラーバーを追加 (標高の凡例)
    plt.colorbar(img_plot, label='Elevation (meters, assumed)')

    # タイトルと軸ラベルを設定
    plt.title(f'Elevation Data from {tif_file_path.split("/")[-1]}')
    plt.xlabel('Longitude')
    plt.ylabel('Latitude')

    # グリッドを追加 (必要に応じて)
    plt.grid(True)

    # 図を表示
    plt.show()

    print("\n図化が完了しました。")

except rasterio.errors.RasterioIOError as e:
    print(f"エラー: TIFFファイルの読み込み中に問題が発生しました。ファイルが存在するか、破損していないか確認してください。\n詳細: {e}")
except Exception as e:
    print(f"予期せぬエラーが発生しました: {e}")

 BelowはOutputです。このShapeからThinkすると、おそらくKagoshimaPref.で左上の高標高が韓国岳や開聞岳、霧島連山で、中央付近のIslandは桜島ではないかとImageしました。ここまではSimpleなOperationです。


 次は、Some Tileを使って広域なDEMDataBaseをCreatしていきます。

(参考)Geospatial Information Authority of JapanのDEM_Tileの活用に関するShikuu_Blog:https://shikuuk.blogspot.com/2025/02/python-download-digital-elevation.html







コメント