2017年12月21日木曜日

S-101 with FOSS4G (1) ISO8211の解析

これは「FOSS4G Advent Calendar 2017」の21日目の記事です。

はじめに

現在一般的に普及している航海用の電子海図は、国際水路機関(IHO)がS-57という名前で公開している規格に基づくものです。以前にも書いたとおり、S-57で作成されたファイルは、GDAL/OGRでベクターファイルとして読み込むことができ、QGISでも表示することができます。

このS-57に代わる新しい電子海図の規格として、IHOでは、S-101という仕様を作っています(なぜ新しい規格が必要なのか等の背景については、別の記事で書いていますので、そちらをご参照ください)。この記事の執筆時点では、S-101はまだ完成しておらず、IHOのタイムスケジュールによると2019年の後半に初版が出るものとみられます。
S-100系のタイムスケジュール(IHO HSSC9の資料より)

ということで、(まだ誰もデータを作ってないので当たり前といえば当たり前ですが、)今のところGISソフトでS-101データを読み込む仕組みは、私が知る限りはまだ存在しないので、とりあえずQGISでS-101を表示するくらいまではやってみたいなと思い始めました。

QGISでS-101を表示するまでの道のり

言ってはみたものの、ちょっと考えただけでも下記のことをやらなければならず、道のりはかなり長そうなので、まず今回は下記の1だけやってみることにします。
  1. PythonでS-101のデータをISO 8211構造として読めるようにする。 ←今回はこれ
  2. ISO 8211構造をS-100のGFMに近いモデルに変換する。
  3. S-101 Feature Catalogueを使ってenum値などを変換する。
  4. QGISのレイヤーに変換して表示するプラグインを作る。
  5. S-100特有の課題の解決(属性の階層構造、Information Type、各種Associationなど)
  6. (GDAL/OGRで直接扱えるようになるといいなあ)

環境

とりあえず次の環境でやりました。
  • Ubuntu 16.04 LTS (Windows Subsystem for LinuxでWindows 10の上にインストール)
  • Python 2.7.6

データの入手

どの国も正式なデータを作っていませんので、IHOが公開しているテストデータを使うしかありません(これも少し古いのですが、これしかないので仕方ありません)。
こちらからデータをダウンロードし、zipを展開して、適当なデータファイル(拡張子が.000のもの)を拾います。
https://www.iho.int/mtg_docs/com_wg/S-100WG/TSG3/S101TestDatasetsExchangeSet.zip

ファイルの解析

PythonでISO 8211のファイルを扱うライブラリがオープンソースで公開されているので、それを使わせていただくことにします。
https://github.com/freekvw/iso8211

このソースをgit cloneで取得して中を見てみると、コマンドラインツール(拡張子なしのiso8211という名前のファイル)が付属しています。どうやらこれで.000の中身を見られそうなので、まずはきちんと読めるかどうか確認してみます。
$ ./iso8211
Interactive command environment
(use exit or `EOF' to exit the environment)
 
iso 8211: file ../AADLULBD01.000
Opening DDF /home/xxxxxxxx/AADLULBD01.000
Warning: In field `CSID' the field controls `1100;&   ' indicate format `I'
         but the actual format controls are `(b11,b14,b11)'
(以下、Warningが大量にでます)
Warningが大量にでますが、読み込めてはいるようです。
中身を少し見てみます。
iso 8211: show record 1
Record 1 at offset 3025
    Leader
        record length              = 8928
        leader id                  = `D'
        base address of field data = 133
        entry map:
            size of field length   = 4
            size of field position = 4
            size of field tag      = 4
    Directory contains 9 entries
    Field 0
        tag  = 'DSID'
        data = b11   'RCNM': 'U:0x0a (10)'
               b14   'RCID': 'U:0x00000001 (1)'
               A     'ENSP': 'S-100 Part 10a'
               A     'ENED': '1.1'
               A     'PRSP': 'INT.IHO.S-101.1.0.0'
               A     'PRED': '1.0.0'
               A     'PROF': '1'
               A     'DSNM': 'AADLULBD01__.000'
               A     'DSTL': ''
               A(8)  'DSRD': '20150706'
               A     'DSLG': 'EN'
               A     'DSAB': ''
               A     'DSED': '1'
               b11   'DSTC': 'U:0x0e (14)'
               b11   'DSTC': 'U:0x12 (18)'
    Field 1
        tag  = 'DSSI'
        data = b48   'DCOX': 'F:0x0000000000000000'
               b48   'DCOY': 'F:0x0000000000000000'
               b48   'DCOZ': 'F:0x0000000000000000'
               b14   'CMFX': 'U:0x00989680 (10000000)'
               b14   'CMFY': 'U:0x00989680 (10000000)'
               b14   'CMFZ': 'U:0x00000064 (100)'
               b14   'NOIR': 'U:0x00000005 (5)'
               b14   'NOPN': 'U:0x000007d6 (2006)'
               b14   'NOMN': 'U:0x000004bc (1212)'
               b14   'NOCN': 'U:0x00000881 (2177)'
               b14   'NOXN': 'U:0x0000026b (619)'
               b14   'NOSN': 'U:0x00000084 (132)'
               b14   'NOFR': 'U:0x000008ff (2303)'
(以下略) 
なんとなくよさそうです。というかこれデータのダンプするのに非常にいいツールなので、業務でも使わせてもらいます。

次に、Pythonのソースコードでデータ構造を扱ってみます。
こんな感じでできそうです。
>>> import iso8211
>>> ddf = iso8211.DDF()
>>> ddf.open("../AADLULBD01.000", "r")  # ファイルを開く
>>> record = ddf[2]  # 3番目のレコードを取得
>>> record.show()
Record 3 at offset 12103
    Leader
        record length              = 62
        leader id                  = `D'
        base address of field data = 41
        entry map:
            size of field length   = 2
            size of field position = 2
            size of field tag      = 4
    Directory contains 2 entries
    Field 0
        tag  = 'IRID'
        data = b11   'RCNM': 'U:0x96 (150)'
               b14   'RCID': 'U:0x00000001 (1)'
               b12   'NITC': 'U:0x00ca (202)'
               b12   'RVER': 'U:0x0001 (1)'
               b11   'RUIN': 'U:0x01 (1)'
    Field 1
        tag  = 'ATTR'
        data = b12   'NATC': 'U:0x008b (139)'
               b12   'ATIX': 'U:0x0001 (1)'
               b12   'PAIX': 'U:0x0000 (0)'
               b11   'ATIN': 'U:0x01 (1)'
               A     'ATVL': '4'
>>> field = record[0]  # 親フィールドを取得
>>> field = record[1]  # 最初の子フィールドを取得
>>> tag = field.tag  # フィールドのタグを取得
>>> print(tag)
ATTR
>>> subfields = field.split()  # フィールドのすべてのサブフィールドを取得
>>> print(subfields)
[('NATC', b12, '\x00\x8b'), ('ATIX', b12, '\x00\x01'), ('PAIX', b12, '\x00\x00'), ('ATIN', b11, '\x01'), ('ATVL', A, '4')]

今回はここまでです。
なお、この段階では、まだファイルをISO 8211として読んでいるだけなので、S-57のENCファイルでもまったく同じことができます。

2017年の振り返り

今年は初めてFOSS4G Tokyoで登壇させていただきました。お世辞にもうまくできたとは言えませんが、コミュニティで発表させていただくという貴重な経験をさせていただいたことは、私にとって何物にも代えがたい財産になりました。OSGeoの関係者のみなさまや、私の話に興味を持ってくださったみなさまに、この場を借りて感謝いたします。

2017年5月6日土曜日

CNTKのチュートリアルを動かしてみる

Microsoftが公開している機械学習フレームワーク「CNTK」を触ってみました。

環境構築

次の環境で試しました。これらのインストールは終わっているものとします。

  • Windows 10 Pro (64bit)
  • Anaconda 4.2.0


Python仮想環境の作成

コマンドプロンプトを起動し、次のコマンドで"cntk"という名前の仮想環境を作成します。Pythonのバージョンは3.5にしておきます。
conda create -n cntk python=3.5

Python仮想環境の起動

activateコマンドで仮想環境を起動します。
activate cntk

CNTKのインストール

CNTKをインストールする前に、いくつかのライブラリをインストールしておきます。
conda install jupyter
conda install matplotlib
conda install scipy
その後、CNTKの本体をインストールします。
pip install https://cntk.ai/PythonWheel/CPU-Only/cntk-2.0rc2-cp35-cp35m-win_amd64.whl


サンプルプログラムのダウンロード

次のコマンドでCNTKのサンプルプログラムをダウンロードします(カレントフォルダーにダウンロードされます)
python -m cntk.sample_installer

チュートリアルの起動

Jupyterを起動します。
jupyter notebook
Jupyter Notebook上で、ダウンロードしたサンプルプログラムの中から、Turorialsフォルダーの中のCNTK_101_LogisticRegression.ipynbをクリックして、ノートを表示させます。


2017年5月4日木曜日

GIS関係者に知ってほしい次世代海洋データ標準S-100

はじめに

国際水路機関(IHO)は、2010年に、「S-100」と呼ばれる新しい海洋データ標準をリリースしました。
IHOが現時点で公開している海洋データ標準としては、ほかに「S-57」と呼ばれる仕様があり、電子海図のデータ仕様として広く普及しています。しかし、この仕様は拡張性(データ定義の見直しの都度、仕様をバージョンアップしなければならない)やメンテナンス性(仕様のバージョンアップのたびに、ECDISなどの表示装置側でソフトウェアアップデートが必要になる)などの面で問題があり、これらを改善するためにS-57を全面的に見直して新たな標準を作る、というのがS-100の背景になっています。

S-100の特徴

S-100の大きな特徴として、次の2点をあげておきます。

地理情報の標準への対応

S-100は、地理情報のグローバルスタンダードであるISO19100シリーズをベースに(ところどころS-100独自の拡張を加えて)作られています。多くのデータはGMLファイルとして配布されると思われるので、一般的なGISソフトウェアでも扱いやすくなります。

データフォーマットとデータ定義の分離

S-100では、データ作成のためのフレームワーク(データモデルやファイルフォーマットなど)のみが提供され、具体的なデータの内容を決めるのは、個々のデータ仕様の役割となります。たとえば、「S-101」というデータ仕様では、S-100で定めるデータモデルに基づいて、電子海図ドメインのデータの定義(「海岸線」「航路標識」など)を行います。


このような分離を行うことによって、表示装置でS-100のフレームワークにさえ正しく対応しておけば、データ仕様の変更やデータ仕様そのものの追加があった場合でも、表示装置側のアップデートを行うことなく、仕様の変更に対応できることになります。

S-100の現状

データ仕様の大半はIHOで作成途中ですので、これらのデータが一般に出回るのは、まだまだ先の話になります。
主要なものを下の表に挙げます。
  • S-101(電子海図)…2019年リリース予定
  • S-102(水深)…リリース済
  • S-111(潮流)
  • S-121(境界情報)
  • S-122(MPA:海洋保護区域)…2019年リリース?
  • S-123(無線サービス)
  • S-124(航行警報)
今後どれだけ普及するかは正直わかりませんが、海洋GISデータはすべてS-100ベースのデータになる、という未来もあるかもしれません。

技術的な話

S-100のデータ構造を扱えるライブラリの存在を現時点で確認できていませんが、前述のとおり、S-100はISO19100シリーズが基になっているため、GeoToolsのOpenGIS実装(org.opengisパッケージ)の内容がかなり参考になるはずです。
S-100対応のECDISのSDKがあるようなので、こういうものの中にはおそらく入っているのでしょう。

参考資料

2017年4月15日土曜日

AutoCAD Map 3Dの情報源まとめ

AutoCAD Map 3Dの情報は、AutoCADに比べて圧倒的に少ないですが、見つけたものをまとめておきます。



2017年1月22日日曜日

TensorFlowを試す

GoogleのディープラーニングフレームワークであるTensorFlowを触ってみました。

環境構築

今回は、Windows 10 Professional (64bit)にAnacondaをインストールし、AnacondaでPythonの仮想環境を作って、その上にTensorFlowをインストールしました。


なお、こちらの資料を参考にさせていただきましたが、VirtualBoxのインストールおよびubuntuの仮想マシンの作成は行っておりません。
Windows+VirtualBoxで作るTensorFlow環境

Anacondaのインストール

Anacondaのダウンロードサイトにアクセスし、Python 3.5版の"64-BIT INSTALLER"をダウンロードします。

ダウンロードしたインストーラーを起動し、あとは画面の指示に従ってインストールを進めればOK。パスを通すのを忘れずに。

Python仮想環境の作成

Windowsのコマンドプロンプトを起動し、次のコマンドで"tensorflow"という名前の仮想環境を作成します。
conda create -n tensorflow python=3.5

Python仮想環境の起動

次のコマンドを実行します。これで仮想環境が起動します(プロンプトの左に"(tensorflow)"と表示されるようになります。
activate tensorflow

TensorFlowのインストール

上で作った仮想環境に対して、次のコマンドでインストールできます。思ったより簡単。
pip install tensorflow

コーディング

上記の状態でコマンドプロンプトからpythonを起動し、あとはTensorFlowの"MNIST for Beginners"のチュートリアルを見ながら、1行ずつコーディングしていきます。