CDOを使う

#cdoとは

Climate Data Operator の略。気候モデルや数値気象予報のデータを操作するコマンドラインツールである。
[cdoのページ](https://code.mpimet.mpg.de/projects/cdo/)
色々と便利なコマンド群が満載である。その一部で自分が使ったことがあるものついてメモがてらまとめた。
詳細はマニュアルを参照のこと。
[cdoマニュアル](https://code.mpimet.mpg.de/projects/cdo/embedded/cdo.pdf)

例は基本、最後尾が出力ファイル。

## 解像度変更
regrid を使う。内挿方法はほかにも色々選べる（例は線形内挿）。

```bash
$ cdo  remapbil,r360x181 t.nc t.1deg.nc
```

### 全球格子（緯度経度格子、ガウス格子）以外の場合

例えばランベルト正角円錐図法で作成された格子を緯度経度格子に変更したい場合。
netcdfに投影法の定義が書いてあれば、以下の定義は必要ない。
（例えば、attributeにgrid_mapping:lambert_conformal_conic、int lambert_conformal_conicという変数があるなど）

```:grid_input
#はコメントアウトのつもり。ただし、実際にコメントアウトとして働くか調べていない。
gridtype = projection
xsize = 800 # x方向の格子数
ysize = 800 # y方向の格子数
xunits = 'meter' # dxの単位
yunits = 'meter' # dxの単位
xinc = 1000 # dx
yinc = 1000 # dy
xfirst = 0.
yfirst = 0.
grid_mapping = crs
grid_mapping_name = lambert_conformal_conic
# lon_0:中心経度、lat_0、中心緯度、
# lat_1,lat_2: 
# x_0,y_0:領域の南西端から中心経度、緯度までの距離[m]
proj_params ='+proj=lcc +lon_0=140. +lat_0=35. +lat_1=30. +lat_2=60. +x_0=400000. +y_0=300000.'
```

proj_paramsの詳細はPROJ のページを見ること。例えばlambert_comformal_conicのパラメータなどは[ここ（projのリンク）](https://proj.org/operations/projections/lcc.html)に書いている。
他にもいろいろな投影法に対応していると思う。

```bash
$ cdo  setgrid,grid_input t.nc t.set_grid.nc
```

これに対し内挿する緯度経度座標を以下のように定義する。

```:grid_output
gridtype =latlon
xsize = 201 # xの格子数
ysize = 201 # yの格子数
xunits = 'degree'
yunits = 'degree'
xfirst = 139 #南西端
xinc = 0.01 # dx
yfirst = 34.5 #南西端
yinc = 0.01 # dy
```

内挿する。

```bash
$ cdo  remapbil,grid_output t.set_grid.nc t.001deg.nc
```

逆をやれば、緯度経度をランベルト正角円錐図法とかもできるはず。

## ファイルを結合
### merge
入力順にくっつける。各ファイルは次元がそろっている（結合する次元以外）必要あり。


```bash
$ cdo merge t.1000hPa.nc t.975hPa.nc t.950hPa.nc t.1000-950hPa.nc
```

### mergetime
時間方向に結合する。ファイルの順序をばらばらに入れても自動的に時間順に結合される。
たとえば、00, 06, 12, 18 UTCに分かれたファイルを結合する際とかは便利。

```bash
$ cdo mergetime t.00.nc t.06.nc t.12.nc t.18.nc t.4day.nc
```

## 切り取り
sel**を使う。色々あるので自分が使ったことあるのだけ。

例)年の切り取り

```bash
$ cdo -selyear,2000,2010 pr.nc pr_2000-2010.nc
```
##　平均
日平均(daymean)、月平均(monmean)、年平均(yearmean)など

```bash
$ cdo daymean pr.nc pr.day.nc
```
## 次元の調整
時間次元をいじったり、緯度経度を修正したりとか。。。


## 計算
cdoは簡単な計算をして、出力を新たなnetcdfに保存することが出来る。
演算子はadd, sub, mul, divなど

#### ばらばらのファイル内の変数を計算する場合

変数が一つなら簡単。（例は割り算）
(prw.nc 割る sprw.nc => crh.nc出力)

```bash
$ cdo div prw.nc sprw.nc crh.nc
```
定数をかけたりするとき。???cを使う（mulcとか）。

```bash
$ cdo mulc,2.5e6 evap.nc lhf.nc
```

#### 同一ファイル内の変数を計算するの場合
exprを使う。expr,'変数の式'で演算を指定。(例参照)
例）

```bash
cdo expr,'ini_sfc_lw_net_all_daily=ini_sfc_lw_up_all_daily-ini_sfc_lw_down_all_daily;' in.nc out.nc
```

#### パイプライン
たとえばmergeして時間平均

```bash
$ cdo daymean -merge t.1000hPa.nc t.975hPa.nc t.950hPa.nc t.1000-950hPa.day.nc
```

#### 計算結果の変数名を変更する
cdoで計算した後の結果は、元のnetcdfファイルの変数名で出力されてしまう。
setpartabnで変換する。事前に適当なファイルに変更するパラメータを書いておく（次の例ではmypartab）

```bash
		cat <<EOF> mypartab
&parameter
name=olr # 変更対象の変数名
out_name=rlut　＃出力する変数名
standard_name=outgoing_long_wave_radiation
long_name="outgoing long wave radiation"
units ="W m-2"
/
EOF
$ cdo setpartabn,mypartab,convert olr.nc rlut.nc
```

#### いくつか例
気が向いたら足す。
湿潤静的エネルギーの計算（パイプライン利用）

```bash
cat <<EOF> mypartab
&parameter
name=z
out_name=mse
standard_name=moist_static_energy
long_name="Moist static energy"
units ="W m-2"
/
EOF
t=t.nc
q=q.nc
z=z.nc
h=h.nc

cdo -f nc4 -z zip_1 -b 32 setpartabn,mypartab,convert \
        -add $z -add -mulc,1004 $t  \
        -add -mulc,2.5e6 $q \
        $h 
```

## その他

### 緯度の南北逆にする。
再解析: N->S をS->Nに。gribを変換して作ったnetcdfで南北を変更するために使用した。

```
$ cdo -invertlat in.nc out.nc
```

### netcdf4で圧縮をかける。

データ量が少し減る。zip_1~zip_9まで選べて、zpi_9が最も圧縮されるが、そこまで圧縮される訳では無い。zip_1で十分だと思う。

```bash
$ cdo -f nc4 -z zip_1 ...
```

### 2byte integer で圧縮されているファイルを演算する

いったんfloatに変換してから計算する必要がある。

```bash
$ cdo -b 32 ...
```