国土地理院基盤地図情報のGMLファイルをGNU Parallelを使用して並行処理するシェルスクリプト
国土地理院の基盤地図情報サイトで公開されている基本項目や数値標高モデルのGMLファイルをGNU Parallelを使用して並行処理するシェルスクリプトを紹介します。
基盤地図情報の基本項目のGMLをパースすると、道路縁、建築物の外周線、軌道の中心線等の情報をポリゴンや線として取得することができます。
これらのデータを使用して、例えば地図を描画や各種の可視化、機械学習のための前処理データ作成などを行うことができます。
いっぽう、データは多数のメッシュに分けて公開されているため、少し大きな領域、例えば東京都を覆う領域のデータを扱いたい場合は、合計で64個ほどのファイルを処理することになります。
例えば、東京都を覆うサイズのメッシュの基本項目のGMLファイルは、次のような64ファイルほどになりました。
FG-GML-533900-ALL-20200401.zip
FG-GML-533901-ALL-20210101.zip
FG-GML-533902-ALL-20200401.zip
FG-GML-533903-ALL-20201001.zip
FG-GML-533904-ALL-20210101.zip
FG-GML-533905-ALL-20201001.zip
FG-GML-533906-ALL-20201001.zip
FG-GML-533907-ALL-20210101.zip
# 中略
FG-GML-533977-ALL-20201001.zip
また、配布されているGMLはzipで圧縮されており、その中に「海岸線」、「道路縁」、「軌道の中心線」、「水涯線」、「建築物の外周線」等の項目が各レイヤーに別れたGMLとして納められた構造になっています。
例えば、FG-GML-533962-ALL-20210101.zipのようなzipファイルについてみてみます。
次のように、建築物、建築物の外周線、道路縁や道路構成線のようなレイヤーに分けられたGMLが入っていることがわかります。
$ unzip -l FG-GML-533962-ALL-20210101.zip
Archive: FG-GML-533962-ALL-20210101.zip
Length Date Time Name
--------- ---------- ----- ----
119964 12-07-2020 19:21 FG-GML-533962-AdmArea-20210101-0001.xml
669525 12-07-2020 19:21 FG-GML-533962-AdmBdry-20210101-0001.xml
4454 12-07-2020 19:21 FG-GML-533962-AdmPt-20210101-0001.xml
75906887 12-07-2020 19:21 FG-GML-533962-BldA-20210101-0001.xml
59727811 12-07-2020 19:21 FG-GML-533962-BldL-20210101-0001.xml
13543050 12-07-2020 19:21 FG-GML-533962-Cntr-20210101-0001.xml
1599365 12-07-2020 19:21 FG-GML-533962-CommBdry-20210101-0001.xml
52556 12-07-2020 19:21 FG-GML-533962-CommPt-20210101-0001.xml
85891 12-07-2020 19:21 FG-GML-533962-ElevPt-20210101-0001.xml
26005 12-07-2020 19:21 FG-GML-533962-GCP-20210101-0001.xml
476156 12-07-2020 19:21 FG-GML-533962-RailCL-20210101-0001.xml
3332794 12-07-2020 19:21 FG-GML-533962-RdCompt-20210101-0001.xml
18494372 12-07-2020 19:21 FG-GML-533962-RdEdg-20210101-0001.xml
117906 12-07-2020 19:21 FG-GML-533962-SBAPt-20210101-0001.xml
837283 12-07-2020 19:21 FG-GML-533962-SBBdry-20210101-0001.xml
2348559 12-07-2020 19:21 FG-GML-533962-WA-20210101-0001.xml
4720822 12-07-2020 19:21 FG-GML-533962-WL-20210101-0001.xml
113577 12-07-2020 19:21 FG-GML-533962-WStrA-20210101-0001.xml
210531 12-07-2020 19:21 FG-GML-533962-WStrL-20210101-0001.xml
4873 11-30-2020 10:26 fmdid21-0101.xml
--------- -------
182392381 20 files
このため、「東京都全域の建物のポリゴンを取得して一定の処理を行った後DBに登録する」ような処理をしたい場合は、64個のGMLファイルの中の、ファイル名にBldAを含むXMLファイルをパースして処理し、DBに登録する処理を実行することになります。
すると、各処理について相応の時間がかかることが想定されるため、「ファイルをパースして処理し、DBに登録する処理を実行」を並行して処理したくなります。
そこでシェルスクリプト
ここでは、GNU Parallelをbashのシェルスクリプトの中で使用して10並行の並行処理を行うようにしました。
次のようなスクリプトになりました。
#!/usr/bin/env bash
path_and_filenames=()
for i in `ls $PWD/*zip`; do
gml_filenames=`unzip -l $i | grep "BldA" | awk '{print $4}'`
for j in $gml_filenames; do
path_and_filenames+=("${i},${j}")
done
done
function process() {
o=$1
list=(${o//,/ })
path=${list[0]}
filename=${list[1]}
# ここで、各ファイルのGMLからpostgisに登録する処理 ogr2ogr使用
# まず解凍
unzip -o -j $path $filename -d $PWD
# 解凍したファイルを使用してベットの処理を行ったのちにDBに登録
# CやRustで書いた別のコマンドに当該ファイルを引数で与えて実行します(割愛)
# 完了したら、解凍済みのファイルを削除
rm $PWD/$filename
}
export -f process
parallel --progress -j 10 "process {}" ::: ${path_and_filenames[@]}
MacBook Pro(2016年前後の古いもの。Intel Core i5 3.1 GHz、メモリ 16 GB)を使用した場合、東京全体のBldAレイヤーの約770万行のインポートが2時間で完了しました。