JASMES Tutorial
 JASMES MODISデータをnetCDF変換したい (Pythonを使ったnetCDF変換)

JASMESサービスで提供しているバイナリ形式のMODISデータをnetCDF変換するチュートリアルです。

注意

事前にJASMESデータのダウンロードが必要となり、JASMESデータ利用にはユーザ登録が必要です。

サンプルスクリプトはPython3を使用します。
本チュートリアルでは、Linux環境での実行例を示しますが、サンプルスクリプトについてはWindows環境でも使用できます。
詳細は本チュートリアルの「1.サンプルスクリプトの使用方法」をご確認ください。

また利用者が本ホームページの内容(スクリプト含む)を用いて行う一切の行為についてJAXAは責任を負うものではありません。

JASMESユーザ登録の詳細は以下のページをご参照ください。JASMESユーザはJASMES関連サービスで公開している全てのデータを利用できます。
本チュートリアルでは、MODISデータ(*_le)をnetCDFに変換します。
JASMESユーザ登録 JASMESデータ取得方法 JASMESデータ一覧

0. はじめに

当チュートリアルは目的に応じて以下のようにご利用ください。

netCDF作成をしたい場合
 「1. サンプルスクリプトの使用方法」に沿って、スクリプト実行をしてください。

サンプルスクリプトの処理の内容を知りたい場合
 「2. スクリプト内容説明」をご参照ください。

1. サンプルスクリプトの使用方法

1-1. スクリプトダウンロード

使用するサンプルスクリプトです。以下のボタンよりダウンロードしてください。
当チュートリアルは、「*_le」のファイル用のスクリプトを提供していますが、netCDF変換方法(2-2)は共通となります。
バイナリファイルの読み込み方法(2-1)については、ファイルの種類によって異なりますので、こちらのチュートリアルに記載のスクリプトをご確認ください。

サンプルスクリプトについて

サンプルスクリプトはPython3を使用し、Pythonライブラリはctypes、NumPy、netCDF4を使用します。
本チュートリアルでは、Linux環境での実行例を示しますが、サンプルスクリプトについてはWindows環境でも使用できます。

サンプルスクリプトの改変は自由で再配布も可能です。

サンプルスクリプト (ファイル名「*_le」) ダウンロード

1-2. 実行環境

当チュートリアルではLinux環境での実行方法を記載しています。
またサンプルスクリプト内の処理では、Python3を使用しています。

サンプルスクリプト動作確認時の実行環境、使用するPythonライブラリは以下です。

実行環境

Linux:Red Hat Enterprise Linux(8.4)
Python:Python 3.6.8
Python標準ライブラリ:ctypes
Python外部ライブラリ:NumPy, netCDF4 ※要インストール


1-3. 対象データ

JASMESデータを取得する場合は、こちらからユーザ登録が必要となります。ユーザ登録後のデータの取得方法はこちらをご参照ください。
JASMES提供データの一覧に、それぞれのプロダクトの領域、解像度、統計期間(Daily、Monthly等)の詳細がありますので、必要に応じてご参照ください。

1-4. サンプルスクリプトの使用方法

入力ファイルパスを引数として、サンプルスクリプトを実行します。
出力ファイルは入力ファイルに.ncをつけたファイル名の物が、スクリプトと同じディレクトリに出力されます。
サンプルスクリプトの冒頭に使用方法の記載がありますので合わせてご確認ください。

$ ./MODIS_le_bin2nc.py <Input>

引数1 Input :
 入力となるバイナリファイルをフルパスで指定します。

コマンド実行例は以下の通りです。
[DIR] : データの入出力ディレクトリ

$ ./MODIS_le_bin2nc.py [DIR]/MDS02SSH_A20230101Av1_v811_7200_3601_CHLA_le 

2. スクリプト内容説明

ここから、サンプルスクリプトの各種処理について説明します。

2-1. Pythonでバイナリファイルの読み込み

JASMES MODISデータのフォーマットに合わせ、ヘッダの指定をしています。
JASMES MODISデータは、ヘッダ部分にピクセルサイズ等の必要な情報を掲載するフォーマットとなっているため、ヘッダ読み込み処理を行う必要があります。
こちらはJASMES MODISデータ特有の内容となりますのでご注意ください。

# Header format
class headerFormat(c.Structure):
  _fields_ = [
    ("npixel" , c.c_char*6 ),
    ("nline"  , c.c_char*6 ),
    ("lon_min", c.c_char*8 ),
    ("lat_max", c.c_char*8 ),
    ("reso"   , c.c_char*8 ),
    ("slope"  , c.c_char*12),
    ("offset ", c.c_char*12),
    ("dum1 ", c.c_char*1),
    ("prod ", c.c_char*8),
    ("dum2 ", c.c_char*1),
    ("file ", c.c_char*40)
  ]

引数(入力バイナリファイルパス)の取得をしています。

argvs   = sys.argv

# argument ERROR
if len(argvs) != 2:
  print("argument error: input file")
  sys.exit(9)
else:
  binfile = argvs[1]

# parameter pick
# 0        1            2    3    4    5    6
# MDS02SSH_A20250501Av1_v811_7200_3601_OLST_le
infile = os.path.basename(binfile)
output = infile + '.nc'
parts = infile.split('_')
X_SIZE = int(parts[3])
Y_SIZE = int(parts[4])

バイナリファイル読み込みをしています。
ファイルに応じてヘッダ情報をformat_dataに読み込んだ後、ヘッダ分をスキップしてデータ部をbinarrに読み込んでいます。

# 1 line * 2byte
HEADER_SIZE = X_SIZE*2
format_data = headerFormat()

# Binary file open
with open(binfile, 'rb') as f:
  # Read header
  f.readinto(format_data)
  # Header skip
  f.seek(HEADER_SIZE)
  # Read binary data as unsiged-2byte integer
  binarr = np.fromfile(f, dtype=np.uint16)

format_dataに読み込んだヘッダの必要な値の取得をしています。

# Header value set
X_SIZE        = np.uint16(format_data.npixel)
Y_SIZE        = np.uint16(format_data.nline)
UpperLeft_LON = np.float32(format_data.lon_min)
UpperLeft_LAT = np.float32(format_data.lat_max)
RESO          = np.float32(format_data.reso)
SLOPE         = np.float32(format_data.slope)
OFFSET        = np.float32(format_data.offset)
PROD          = format_data.prod.decode('utf-8').rstrip('\x00')
PROD          = PROD.replace(' ','')

2-2. PythonでnetCDFの出力

出力用にnetCDFを開きます。 2-1で取得したヘッダ情報X_SIZE、Y_SIZEを使用して、netCDFの次元の定義をします。

# netCDF
with nc.Dataset(output, 'w', format='NETCDF4') as ds:
# 次元の定義
  ds.createDimension('longitude', X_SIZE)
  ds.createDimension('latitude', Y_SIZE)

netCDFの変数の定義と値の設定をします。

  # 変数の定義
  longitudes = ds.createVariable('longitude','f4',('longitude',))
  latitudes = ds.createVariable('latitude','f4',('latitude',))
  data_var = ds.createVariable(PROD, 'i2', ('latitude', 'longitude'))

  # 値の設定
  longitudes[:] = np.linspace(0,360,X_SIZE)
  latitudes[:]  = np.linspace(-90,90,Y_SIZE)
  data_var[:,:] = orgdat

netCDF属性の追加をします。
ここではヘッダで取得したSlope/Offetのみ追加していますが、必要に応じて追記してください。

  # 属性の追加
  data_var.scale_factor = SLOPE
  data_var.offset = OFFSET