emaita 備忘録 http://blog.emaita.jp/ あるいは、今日やらなくていいことを今日やらないことは正当であることの迂遠な証明 en-us Sun, 22 Sep 2019 00:00:00 +0900 http://blog.emaita.jp/2019/09/22/msdosfs.html http://blog.emaita.jp/2019/09/22/msdosfs.html <![CDATA[mount_msdosfs の文字コード]]> mount_msdosfs の文字コード

21世紀になってから20年近くも経つと言うのに、私たちは未だに 文字化けに取り憑かれている。滑稽である。

MS-DOS時代(だいたい1990年代後半)のMOディスクの中身を取り出そうと思い、 FreeBSD機に繋げて mount_msdosfs を使用したところ、ファイル名に関連して エラーが出た。カーネルハックして原因が判ったので、対策を記録しておく。

OS のバージョンは FreeBSD 11.2R 。

直面したエラーには 2種類あった。 チルダ記号(0x7e)に関するものと、「最」の字に関するもの。

チルダ記号(0x7e)のエラー

mount_msdosfs(8) は -D と -L オプションで文字コードを指定するようになっている。 -D はマウントするファイルシステムの文字コードの指定で、 今回は日本語MS-DOSで使用していたMOディスクなので SJIS になる。 -L の方はOS側の文字コードで、-L ja_JP.UTF-8 のようにロケール名を与える。 -D と -L を指定することで、カーネル内部で自動的に文字コードの変換が行われ、 ファイルシステムとOSの文字コードの違いが吸収される仕組みになっている。

さて、ネットを漁ると、mount_msdosfs には -L ja_JP.eucJP を与える方が良い、 と書かれたブログ記事が多いようだ。10年くらい前の記事で、かつて FreeBSD カーネルのマルチバイト化が不十分だった頃の対処法らしい。 しかし現在では UTF-8 でほぼ問題が出ないようだし、これから述べるエラーが出るので EUC-JP を指定する利点はあまりないように思う。

さてそのエラーだが、ファイル名にチルダ記号(0x7e)が含まれている時に発生する。 20年ほど前、MS-DOSとWindows95との併用期に、ファイル名の長さの違いを回避するために MS-DOS側のファイル名にチルダが付与され「REPORT~1.TXT」のようになったりしたことを 覚えている人も多いだろう。今回はこのチルダが悪さをする。

まず、条件と現象を記すと、 mount_msdosfs -D sjis -L ja_JP.eucJP でマウントし、 たとえば REPORT~1.TXT が含まれるディレクトリに対して ls(1) を実行すると、

REPORT?1.TXT: No such file or directory

となる。

原因は、実は SJIS と EUC-JP では 0x7e に割り当てられている文字が違うことにある。 EUC-JP は 0x7f 以下の 7ビット部分の文字セットは ISO646-US で、これは 0x7e が ASCII と同じくチルダ記号になっている。 一方 SJIS は 7ビット文字セットが ISO646-JP で、こちらの 0x7e はチルダではなく 上付き横棒 ‾ (UTF8:0xe280be, UCS2:0x203E)なのである。 さらに、この上付き横棒は EUC-JP には存在しないため、EUC-JP に変換しようとすると EUC-JP の INVALID 記号である〓(いわゆるゲタ文字、EUC-JP:0xAEA2)に置換される。

このため、カーネル内部で次のような処理が行われる。 仮にファイル名を REPORT~1.TXT とすると、 まず SJIS から UCS2 を経由して EUC-JP に変換する。

SJIS:   52 45 50 4f 52 54   7e 31 2e 54 58 54
UCS2:   52 45 50 4f 52 54 203e 31 2e 54 58 54
EUC-JP: 52 45 50 4f 52 54 aea2 31 2e 54 58 54

カーネルはゲタ文字化した文字列をファイル名として保持する。 カーネルからファイルシステムにアクセスする時には逆変換が行われ、 ゲタ文字は INVALID記号ではなく普通の文字として変換される。

EUC-JP: 52 45 50 4f 52 54 aea2 31 2e 54 58 54
UCS2:   52 45 50 4f 52 54 3013 31 2e 54 58 54
SJIS:   52 45 50 4f 52 54 ac81 31 2e 54 58 54

MS-DOSファイルシステムのファイル名は 8.3式なのに 変換後のものは 9.3になっている。9文字目が切り捨てられて、 またエンディアンの関係か下位バイトが先になるようなので、結局

52 45 50 4f 52 54 81 ac 2e 54 58 54

というバイト列を探すことになるが、もちろんこんな名前のファイルは ディレクトリエントリに存在しないので、ENOENT になる。

原因が判ったところで対策だが、SJIS の 0x7e がそのまま 0x7e になるように改造する 方法を試してみた。FreeBSD のソースコードに手を入れて色々試したところ、

/usr/src/share/i18n/esdb/MISC/Shift_JIS.src
/usr/src/share/i18n/esdb/MISC/Shift_JIS-2004.src
/usr/src/lib/libkiconv/quirks.c

を修正すれば良いらしい。

上の2つはSJISの文字セットを定義しているところで、 ファイル内の ISO646-JP のところを ISO646-US に変更する。 quirks.c は文字変換テーブルから 0x7e のエントリをコメントアウトする。 それぞれビルドして、

/usr/share/i18n/esdb/MISC/Shift_JIS.esdb
/usr/share/i18n/esdb/MISC/Shift_JIS-2004.esdb
/lib/libkiconv.so.4

を置き換えてOSを再起動すれば、0x7e 文字の変換が抑制されて、エラーが出なくなった。

「最」のエラー

mount_msdosfs の -L オプションに ja_JP.UTF-8 を指定してもほとんど問題はなかったのだが、 唯一、ファイル名に「最」の字が含まれているとエラーが出た。

条件と現象を記すと、 mount_msdosfs -D sjis -L ja_JP.UTF-8 でマウントし、 たとえば 最初.TXT が含まれるディレクトリに対して ls(1) を実行すると、

最初.TXT: No such file or directory.

とエラーになる。

原因を調べた結果、 /usr/src/sys/libkern/iconv_xlat16.c:iconv_xlat16_toupper()でおかしな挙動が 起こっていることが判った。

MS-DOSはファイル名の大文字小文字を区別せず、ファイル名は大文字で格納される。 そのためカーネルからMS-DOSファイルシステムにアクセスする時に大文字化処理をしていて、 上記関数はその処理をする関数である。この関数は20行程度の短い関数なので、 実際に中を見た方が理解が早い。

static int
iconv_xlat16_toupper(void *d2p, int c)
{
        struct iconv_xlat16 *dp = (struct iconv_xlat16*)d2p;
        int c1, c2, out;

        if (c < 0x100) {
                c1 = C2I1(c << 8);
                c2 = C2I2(c << 8);
        } else if (c < 0x10000) {
                c1 = C2I1(c);
                c2 = C2I2(c);
        } else
                return (c);

        if (dp->d_table[c1] && dp->d_table[c1][c2] & XLAT16_HAS_UPPER_CASE) {
                out = dp->d_table[c1][c2] & 0xffff;
                if ((out & 0xff) == 0)
                        out = (out >> 8) & 0xff;
                return (out);
        } else
                return (c);
}

見て判る通り、1バイト文字はビットシフトして下位バイトを 0 にして、 後で逆方向にビットシフトして元に戻す処理をしている。 そのため、下位バイトが 0 のマルチバイト文字は 1バイト文字に間違えられてしまうのだ。

ここまで書けば想像がつくと思うが、くだんの「最」の字は、UCS2 のコードが 0x6700 なのである。 そのためこの関数においては 0x67 つまり ‘g’ と認識され、これが大文字化して 0x47 ‘G’ が 戻り値になる。

カーネルは G初.TXT というファイル名を探すが、ファイルシステムのディレクトリエントリには そのようなファイル名はもちろん存在しないため、ENOENT になる。

これを回避するため、私は以下のように修正した。

--- iconv_xlat16.c.orig     2018-06-22 08:02:52.000000000 +0900
+++ iconv_xlat16.c  2019-09-22 21:08:40.097838000 +0900
@@ -334,6 +334,8 @@
    } else if (c < 0x10000) {
                 c1 = C2I1(c);
                 c2 = C2I2(c);
+                if (c1 == 0)
+                        return (c);
    } else
            return (c);

この関数はカーネルモジュールの libiconv.ko に格納されるため、 libiconv.ko をリビルドして置き換えれば良い。 Makefile は /usr/src/sys/modules/libiconv/ にある。

予期せぬ副作用があるかも知れないので、mount_msdosfs を使用する時だけ libiconv.ko を入れ替えるようにする方が安全だろう。

]]>
Sun, 22 Sep 2019 00:00:00 +0900
http://blog.emaita.jp/2018/05/09/usb_ids.html http://blog.emaita.jp/2018/05/09/usb_ids.html <![CDATA[USB ID]]> USB ID

smartmontools の USB HDD 対応状況を調べている時に、 手持ちの HDD が Smartmontools USB Device SupportUSB ID Repository に 収録されていないことに気づいた。

折角なのでデータを送ろうかと思ったのだが、そうすると、 手持ちの USB機器を一通り調べて見たくなるのが凝り性の悪いところで、 すぐに出てくる場所にあった機器については下記の通り。 (他に、スキャナとプリンタが押入れにあるが、面倒なので調査対象から外した。 あとUSBメモリも除外)

種別 販売元・製品型番 USB ID USB デバイス名
HDD BUFFALO HD-LB2.0TU2 0411:01ba BUFFALO USB-SATA Bridge
HDD BUFFALO HDF-LB2.0TU2 0411:01ea BUFFALO USB-SATA Bridge
HDD BUFFALO HD-LC3.0U3-BKC 0411:027e BUFFALO HD-LCU3
HDD Logitec LHD-PBE40U2SV 0789:00cc Logitec LHD USB Device
DVD Panasonic LF-P968C 04da:0d14 Panasonic DVD-RAM MLT08
DVD BAFFALO DVSM-PL58U2 0411:00f9 BAFFALO USB2.0 External Mass Storage Device
SATA変換ケーブル GREEN HOUSE GH-USHD-SATA 152d:2339 JMicron JM20339 SATA Bridge
IDE変換ケーブル GREEN HOUSE GH-USHD-IDE 05e3:0702 Genesys Logic
有線LAN BUFFALO LUA3-U2-AGT 0411:006e BUFFALO
無線LAN PLANEX GW-US54GXS 2019:5303 PCI GW-US54GXS
キーボード SANWA Supply SKB-SL09BK 099a:6330 Zippy Technology Corp. USB Keyboard
有線マウス BUFFALO BSMOUK01 093a:2510  
無線マウス ELECOM M-LS14DL 25a7:2410 ARESON Laser mouse
無線マウス ELECOM M-BL2DB 056e:0092 ELECOM Wireless BlueLED Mouse
キーボード切替ケーブル BUFFALO BSKM201BK 2101:1402 ActionStar KM Switch
USBハブ ELECOM U2H-M4BWH 0409:005a (NEC Corp. High Speed Hub)
USBハブ ELECOM U2H-TAP3420SBK 0409:005a (NEC Corp. High Speed Hub)
カードリーダー ELECOM MR-GU2S04SV 0dda:2001 ICSI USB2.0 Card Reader
ヘッドホン BUFFALO 製品名不明 0c76:1607 JMTec, LLC. audio controller USB Headphone Set

販売ブランドと USB のベンダIDが違っているのは OEM 製品ということなのかな。

]]>
Wed, 09 May 2018 00:00:00 +0900
http://blog.emaita.jp/2018/05/09/usbhdd.html http://blog.emaita.jp/2018/05/09/usbhdd.html <![CDATA[USB HDD (2)]]> USB HDD (2)

過去に使用していた USB HDD についても smartctl の結果を記しておく。

BUFFALO HD-LB2.0TU2

テレビ用の1台目。2011年購入。

PC への接続時の dmesg は下記の通り。

ugen1.2: <BUFFALO USB-SATA Bridge> at usbus1
umass0: <BUFFALO USB-SATA Bridge, class 0/0, rev 2.00/1.12, addr 2> on usbus1
umass0:  SCSI over Bulk-Only; quirks = 0x8100
umass0:6:0:-1: Attached to scbus6
da0 at umass-sim0 bus 0 scbus6 target 0 lun 0
da0: <BUFFALO External HDD 0000> Fixed Direct Access SCSI-3 device
da0: 40.000MB/s transfers
da0: 1907729MB (3907029168 512 byte sectors)
da0: quirks=0x2<NO_6_BYTE>

smartctl の -d オプションをいろいろ変えて試してみたが、 結局うまく行かなかった。ドライブ自体には SMART があると思うのだが、 機器側の USB ブリッジが SMART に対応していないのか、 smartctl がこのブリッジに対応していないのか、どちらかだと思うが、 どちらなのかは判らない。

USB ブリッジの USB ID は 0x0411:0x01ba。 中のドライブの型番が読み出せないので中身は不明。

BUFFALO HDF-LB2.0TU2

テレビ用の2台目。確か2012年購入。

PC への接続時の dmesg は下記の通り。

ugen1.2: <BUFFALO USB-SATA Bridge> at usbus1
umass0: <BUFFALO USB-SATA Bridge, class 0/0, rev 2.00/1.00, addr 2> on usbus1
umass0:  SCSI over Bulk-Only; quirks = 0xc101
umass0:6:0:-1: Attached to scbus6
da0 at umass-sim0 bus 0 scbus6 target 0 lun 0
da0: <BUFFALO External HDD 0000> Fixed Direct Access SCSI-3 device
da0: 40.000MB/s transfers
da0: 1907729MB (3907029168 512 byte sectors)
da0: quirks=0x2<NO_6_BYTE>

smartctl の自動推測がうまく働き、-d オプションの指定なしでもうまく行った。 内部的には -d sat を使用しているようだ。

# smartctl -i /dev/da0
=== START OF INFORMATION SECTION ===
Model Family:     Western Digital Green
Device Model:     WDC WD20EARX-00PASB0
Serial Number:    WD-WCAZAE534488
LU WWN Device Id: 5 0014ee 25c684be6
Firmware Version: 51.0AB51
User Capacity:    2,000,398,934,016 bytes [2.00 TB]
Sector Sizes:     512 bytes logical, 4096 bytes physical
Device is:        In smartctl database [for details use: -P show]
ATA Version is:   ATA8-ACS (minor revision not indicated)
SATA Version is:  SATA 3.0, 6.0 Gb/s (current: 1.5 Gb/s)
Local Time is:    Tue May  8 15:24:43 2018 JST
SMART support is: Available - device has SMART capability.
SMART support is: Enabled

中身は WD の緑のようだ。

USB ブリッジの USB ID は 0x0411:0x01ea。

Logitec LHD-PBE40U2SV

ポータブルHDD。いつ頃の購入だったか覚えていないが、 容量 40GB なので、だいぶ昔だということは間違いない。 15年前くらいか?

PC への接続時の dmesg は下記の通り。

ugen1.2: <Logitec Corp. LHD USB Device> at usbus1
umass0: <Logitec Corp. LHD USB Device, class 0/0, rev 2.00/1.16, addr 2> on usbus1
umass0:  SCSI over Bulk-Only; quirks = 0x0000
umass0:6:0:-1: Attached to scbus6
da0 at umass-sim0 bus 0 scbus6 target 0 lun 0
da0: <LOGITEC LHD-PBEU2 1.16> Fixed Direct Access SCSI device
da0: Serial Number 0406122020000689
da0: 40.000MB/s transfers
da0: 37954MB (77730300 512 byte sectors)
da0: quirks=0x2<NO_6_BYTE>
cd1 at umass-sim0 bus 0 scbus6 target 0 lun 1
cd1: <LOGITEC VIRTUAL CD-ROM 1.16> Removable CD-ROM SCSI device
cd1: Serial Number 0406122020000689
cd1: 40.000MB/s transfers
cd1: 109MB (55983 2048 byte sectors)
cd1: quirks=0x10<10_BYTE_ONLY>

da の他に cd デバイスが認識されるのは、製品のマニュアルを 仮想CD-ROM として内部に格納しているからだ。

-d オプションを指定しても、smartctl からは内部が見えなかった。

USB ID は 0789:00cc。

GREEN HOUSE GH-USHD-SATA

これは HDD ではなく、SATA の生ドライブを PC に接続するための変換ケーブル。 購入時期はよく覚えていないが、IDE用のケーブルと一緒に買ったので、 HDD のインターフェイスが IDE から SATA に切り替わりつつある頃だろう。

試しに使い古しの生ドライブを接続すると、下記のような dmesg が出る。

ugen1.2: <JMicron USB to ATAATAPI Bridge> at usbus1
umass0: <MSC Bulk-Only Transfer> on usbus1
umass0:  SCSI over Bulk-Only; quirks = 0xc100
umass0:6:0:-1: Attached to scbus6
da0 at umass-sim0 bus 0 scbus6 target 0 lun 0
da0: <WDC WD80 0JD-08LSA0 > Fixed Direct Access SCSI-2 device
da0: Serial Number DA9A535973FF
da0: 40.000MB/s transfers
da0: 76324MB (156312576 512 byte sectors)
da0: quirks=0x2<NO_6_BYTE>

製品の中身は JMicron 製のようだ。 smartctl の自動推測が効いて、-d オブション無しで SMART が見られる。 内部的には -d usbjmicron が使用されているようだ。

USB ID は 152d:2339。

]]>
Wed, 09 May 2018 00:00:00 +0900
http://blog.emaita.jp/2018/05/08/tinkerer.html http://blog.emaita.jp/2018/05/08/tinkerer.html <![CDATA[Tinkerer 1.7 と Python 2]]> Tinkerer 1.7 と Python 2

新しく Tinkerer 1.7 をセットアップしたのはいいが、ビルドが失敗する。

$ tinker -b
Running Sphinx v1.7.4

Extension error:
Could not import extension tinkerer.ext.blog (exception: No module named builtins)

情報が足りないので、python 上で import を実行してみる。

$ python
Python 2.7.14 (default, Sep 27 2017, 12:15:00)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tinkerer.ext.blog
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/maita/manuscript/webdocs/venv/lib/python2.7/site-packages/tinkerer/ext/blog.py", line 11, in <module>
    from tinkerer.ext import (aggregator, author, filing, html5, metadata, patch,
  File "/Users/maita/manuscript/webdocs/venv/lib/python2.7/site-packages/tinkerer/ext/aggregator.py", line 12, in <module>
    from tinkerer.ext.uistr import UIStr
  File "/Users/maita/manuscript/webdocs/venv/lib/python2.7/site-packages/tinkerer/ext/uistr.py", line 12, in <module>
    import builtins as __builtin__
ImportError: No module named builtins

エラーの真の出所は tinkerer.ext.uistr。Python のビルトインモジュールは、 Python 2 では __builtin__ という名前だが Python 3 で builtins に変わった。 該当のコードは Python 3 で実行した場合にその違いを吸収するためのものだろうが、 Python 2.7 で実行すると逆に builtins モジュールが無いので、ImportError が出るのは当然だ。

uistr.py を直接修正するのが一番簡単だろう。

#import builtins as __builtin__
import __builtin__

面倒だが、まぁ、未だに Python 2 を使い続けている自分が悪いのだ。

]]>
Tue, 08 May 2018 00:00:00 +0900
http://blog.emaita.jp/2018/05/08/usbhdd.html http://blog.emaita.jp/2018/05/08/usbhdd.html <![CDATA[USB HDD の SMART を確認する]]> USB HDD の SMART を確認する

テレビの録画に使用していた USB HDD がエラーを出すようになった。 テレビ本体は 2011年購入の東芝REGZAなのだが、備忘のために症状を詳しく記すと、

  • 予約した録画が開始せず、クイックメニュー > お知らせ > 本機に関するお知らせに「録画機器の接続を確認できなかったため、録画予約を中止しました」というメッセージが追加される。
  • 録画実行中に録画が停止し、クイックメニュー > お知らせ > 本機に関するお知らせに「録画機器にエラーが発生したため、録画予約を中止しました」というメッセージが追加される。
  • 録画再生中に「この操作はできません」と一瞬表示されたあと、画面が真っ暗になる。

HDD のエラーと言うとまず不良セクタを疑う。 その場合は、録画再生で必ず同じ場所でエラーが出る筈だが、 今回の場合はそうではなく、エラーが出る場所がまちまちだったので、 その可能性は低いと思われた。

それよりも、電源や駆動系の劣化によってパフォーマンスが低下し、 スピンアップやヘッドシークが遅くなったりして、 リアルタイム処理に追いつかなくなってるような感じがした。

とは言え、こういう問題について「感じがした」なんていう 印象論を語っても意味はない。不良セクタの有無はディスクの SMART を確認すれば判るのだから、 HDD を PC に接続して実際に SMART を見てみることにした。

PC は FreeBSD 10.4R に pkg で smartmontools 6.6 をインストールしたもの。

HDD は BUFFALO DriveStation HD-LC3.0U3-BKC。確か2015年に購入。

まず、HDD の USB ケーブルを PC に挿した時にコンソールに表示されるメッセージは下記の通り。

ugen1.2: <BUFFALO HD-LCU3> at usbus1
umass0: <BUFFALO HD-LCU3, class 0/0, rev 2.10/1.00, addr 2> on usbus1
umass0:  SCSI over Bulk-Only; quirks = 0xc101
umass0:6:0:-1: Attached to scbus6
da0 at umass-sim0 bus 0 scbus6 target 0 lun 0
da0: <BUFFALO External HDD 0000> Fixed Direct Access SCSI-3 device
da0: 40.000MB/s transfers
da0: 2861588MB (5860533168 512 byte sectors)
da0: quirks=0x2<NO_6_BYTE>

smartctl はデバイスの種類を自動的に推測する機能があるが、 この製品ではうまく推測できないようで、以下のような結果になる。

# smartctl -i /dev/da0
smartctl 6.6 2017-11-05 r4594 [FreeBSD 10.4-RELEASE-p8 amd64] (local build)
Copyright (C) 2002-17, Bruce Allen, Christian Franke, www.smartmontools.org

/dev/da0: Unknown USB bridge [0x0411:0x027e (0x100)]
Please specify device type with the -d option.

USB HDD は中身に SATA ドライブを使用していることが多いようなので、 -d sat を指定してみると、やはり正常にアクセスできるようになった。 (以下、smartctl の出力のコピーライト部分は省略)

# smartctl -i -d sat /dev/da0
=== START OF INFORMATION SECTION ===
Model Family:     Toshiba 3.5" DT01ACA... Desktop HDD
Device Model:     TOSHIBA DT01ACA300
Serial Number:    25PHEW5GS
LU WWN Device Id: 5 000039 ff4f14c2b
Firmware Version: MX6OABB0
User Capacity:    3,000,592,982,016 bytes [3.00 TB]
Sector Sizes:     512 bytes logical, 4096 bytes physical
Rotation Rate:    7200 rpm
Form Factor:      3.5 inches
Device is:        In smartctl database [for details use: -P show]
ATA Version is:   ATA8-ACS T13/1699-D revision 4
SATA Version is:  SATA 3.0, 6.0 Gb/s (current: 3.0 Gb/s)
Local Time is:    Tue May  8 09:12:06 2018 JST
SMART support is: Available - device has SMART capability.
SMART support is: Enabled

中身は東芝製ドライブのようだ。SMART をサポートしているようなので、 まずはエラーログを見てみる。

# smartctl -d sat -l error /dev/da0
SMART Error Log Version: 1
No Errors Logged

エラーは出ていない。次に -A オプションで attribute を確認する。

# smartctl -d sat -A /dev/da0
=== START OF READ SMART DATA SECTION ===
SMART Attributes Data Structure revision number: 16
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  1 Raw_Read_Error_Rate     0x000b   100   100   016    Pre-fail  Always       -       0
  2 Throughput_Performance  0x0005   140   140   054    Pre-fail  Offline      -       67
  3 Spin_Up_Time            0x0007   134   134   024    Pre-fail  Always       -       413 (Average 439)
  4 Start_Stop_Count        0x0012   099   099   000    Old_age   Always       -       6336
  5 Reallocated_Sector_Ct   0x0033   100   100   005    Pre-fail  Always       -       0
  7 Seek_Error_Rate         0x000b   100   100   067    Pre-fail  Always       -       0
  8 Seek_Time_Performance   0x0005   124   124   020    Pre-fail  Offline      -       33
  9 Power_On_Hours          0x0012   099   099   000    Old_age   Always       -       7029
 10 Spin_Retry_Count        0x0013   100   100   060    Pre-fail  Always       -       0
 12 Power_Cycle_Count       0x0032   099   099   000    Old_age   Always       -       4844
192 Power-Off_Retract_Count 0x0032   095   095   000    Old_age   Always       -       6336
193 Load_Cycle_Count        0x0012   095   095   000    Old_age   Always       -       6336
194 Temperature_Celsius     0x0002   222   222   000    Old_age   Always       -       27 (Min/Max 3/62)
196 Reallocated_Event_Count 0x0032   100   100   000    Old_age   Always       -       0
197 Current_Pending_Sector  0x0022   100   100   000    Old_age   Always       -       0
198 Offline_Uncorrectable   0x0008   100   100   000    Old_age   Offline      -       0
199 UDMA_CRC_Error_Count    0x000a   200   200   000    Old_age   Always       -       0

ID 5 や ID 196 から明らかなように、セクタの代替処理がまったく発生していない。 その他の項目も、これと言って悪いところはなさそうに見える。 やはりディスク自体はまあまあ健全で、少なくともデータロストの危険はなさそうだ。

念のため、SMART の自己テストを実行してみる。short テストは 1,2分、long テストは 6時間ちょっと掛かった。

# smartctl -d sat -l selftest /dev/da0
=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error
# 1  Extended offline    Completed without error       00%      7035         -
# 2  Short offline       Completed without error       00%      7029         -

やはりエラーなし。

となるとエラーの原因は、電源かUSBケーブルかインターフェイス部か、ということになるが、 これ以上の原因特定は難しそうなので(エラー自体の再現性が低いので)、 結局新しい USB HDD を購入して交換することにしたのであった。

]]>
Tue, 08 May 2018 00:00:00 +0900
http://blog.emaita.jp/2018/01/31/shapefile.html http://blog.emaita.jp/2018/01/31/shapefile.html <![CDATA[QGISで表示できないshapefile]]> QGISで表示できないshapefile

外部の人から受け取った SHAPE 形式のGISデータを、 QGISで見てみようとしたところ、データはちゃんと入っているっぽいのに 画面には何も表示されない、という状況になり、 原因調査にちょっと時間が掛かったのでメモしておく。

原因

先に結論を述べると、地物のジオメトリが緯度経度座標なのに、 bounding box (以下BBOX)がウェブメルカトル(EPSG3857)座標になっていたのが原因。

受け取ったデータはポリゴンデータだったのだが、 ポリゴンデータのような、複数の座標を持つジオメトリ型の場合、 SHAPEファイル内には、

  • レイヤ全体のBBOX
  • 個々のジオメトリごとのBBOX

が保持される。詳しくは ESRI の解説書 を見よ。

今回のケースでは、レイヤ全体のBBOXはジオメトリデータと同じく 緯度経度座標になっていたのだが、ジオメトリごとのBBOXは 何故か EPSG3857 になっていた。 おそらくQGISは、ジオメトリごとのBBOXを律儀に適用し、 地物の表示をマスクしてしまった、ということだと思われる。

症状

原因調査に時間が掛かったのは、SHAPEファイルを読み込ませた時に QGISが何もエラーを出さなかったからだ。

同様に、ogrinfo もエラーを出さなかった。 ogrinfo を実行すると Extent という表記でBBOXを表示するが、 これはSHAPEファイル内の「レイヤ全体のBBOX」の数値で、 ジオメトリごとのBBOXはまったく出力されない。

原因特定

ogr2ogr を使って SHAPE形式からSHAPE形式に変換したところ、 QGISで表示できるようになったので、バイナリ用diffを使って 変化した部分を特定し、ESRIの説明書と突き合わせて ジオメトリごとのBBOXが不適切であることを突き止めた。

HEX表記の浮動小数点データを10進表記にする作業には、 python の struct モジュールを使用した。

]]>
Wed, 31 Jan 2018 00:00:00 +0900
http://blog.emaita.jp/2016/10/14/ordinance_city2.html http://blog.emaita.jp/2016/10/14/ordinance_city2.html <![CDATA[他の環境関係法令による政令市]]> 他の環境関係法令による政令市

指定都市等のリストは 総務省 を参照するのが確実かな。

さて、いろいろややこしい。

水質汚濁防止法

水質汚濁防止法施行令 第10条に、指定都市と中核市に加えて

  • 福島市
  • 市川市
  • 松戸市
  • 市原市
  • 町田市
  • 藤沢市
  • 徳島市

が挙げられている。

特例市については、かつては令第10条に記載されていたが、 地方自治法改正に合わせて条文から削除し、 H27.1.30付の附則で経過措置として施行時特例市に従来通りの事務委任を 続けるという規定が定められている。

だから実質的には、指定都市、中核市、施行時特例市、上記7市に 水質汚濁防止法の事務が委任されている。

騒音規制法

H23年度までは、(旧)騒音規制法施行令第4条第1項において、

  • 一関市
  • 日立市
  • 土浦市
  • ひたちなか市
  • 桐生市
  • 松戸市
  • 君津市
  • 上田市
  • 多治見市

に、自動車騒音常時監視の事務が委任されていた (H21年度版環境六法で確認)。

指定都市、中核市、特例市、特別区には自動車騒音常時監視に加えて 他の事務も委任されていた(旧令4-2)。

H24年度からは、地方自治の推進のため、すべての一般市にも 指定都市に対するものと同様の事務が委任されるようになった。 それに合わせて令第4条は削除された。

だから現在では、騒音規制法に定める政令市、というものはない。

振動規制法

H23年度までは、(旧)振動規制法施行令第5条において、 指定都市、中核市、特例市、特別区 に事務が委任されていた。

H24年度からは、地方自治の推進のため、すべての一般市にも 指定都市に対するものと同様の事務が委任されるようになった。 それに合わせて令第5条は削除された。

だから現在では、振動規制法に定める政令市、というものはない。

悪臭防止法

H23年度までは、(旧)悪臭防止法施行令第3条において、 指定都市、中核市、特例市、特別区 に事務が委任されていた。

H24年度からは、地方自治の推進のため、すべての一般市にも 指定都市に対するものと同様の事務が委任されるようになった。 それに合わせて令第3条は削除された。

だから現在では、悪臭防止法に定める政令市、というものはない。

ダイオキシン類対策特別措置法

ダイオキシン類対策特別措置法施行令 第8条に、指定都市と中核市に対する事務委任が規定されている。

特例市に関しては、もとから規定がなかったようだ (H21年度版環境六法で確認)。

]]>
Fri, 14 Oct 2016 00:00:00 +0900
http://blog.emaita.jp/2016/10/12/ordinance_city.html http://blog.emaita.jp/2016/10/12/ordinance_city.html <![CDATA[大気汚染防止法に定める政令市]]> 大気汚染防止法に定める政令市

法律に疎いと何処に書いてあるのかわからんのよね。

大気汚染防止法施行令 第13条に規定。

  • 小樽市
  • 室蘭市
  • 苫小牧市
  • 川口市
  • 所沢市
  • 市川市
  • 松戸市
  • 市原市
  • 平塚市
  • 藤沢市
  • 四日市市
  • 吹田市
  • 八尾市
  • 明石市
  • 加古川市
  • 大牟田市

他に、指定都市、中核市、施行時特例市に事務の委譲がある。

川口市、所沢市、平塚市、四日市市、吹田市、八尾市、明石市、加古川市は 大気汚染防止法政令市かつ施行時特例市。

環境省・大気汚染防止法施行状況調査報告書 の末尾に政令市等の一覧がある。

]]>
Wed, 12 Oct 2016 00:00:00 +0900
http://blog.emaita.jp/2016/07/13/standardareacode2.html http://blog.emaita.jp/2016/07/13/standardareacode2.html <![CDATA[いわゆる市区町村コード(2)]]> いわゆる市区町村コード(2)

(承前)

データとしての使いやすさと情報量という点では、 統計LOD から公開されている「標準地域コード」で充分である。 ただ、実際に中身を見たところ、やや不十分なところがあった。

  • 自治体の分割に対応していない。山梨県上九一色村が2分割されて 甲府市と富士河口湖町に編入されたケースなどが正確に記述されていない。
  • 標準地域コード策定時点(1970年4月1日)時点で既に廃止されていた自治体の エンティティが混入していて紛らわしい。

これについては統計LODの問い合わせアドレスにメールで問い合わせたところ、 データを修正する方向で対応する、とのことであった。 そのうちデータがアップデートされるものと思われる。

さて LOD と言えば Sparql とかいう言語で検索したりするものらしいが、 私は当面は自発的にこれを学ぶつもりはない(だってめんどくさそうだし)。 この程度のデータ量だったらどんな方法でも大差はないのだから、 いつも通りに Python + rdflib で スクリプト を書いてみた。 各コードの有効期間と編入・合併先を抽出するスクリプトである。

実行結果は こんな感じ (ただし別途 sort してある)。 元データのライセンスが CC-BY 4.0 なので、このファイルを利用する場合は 元データの権利者を表示すること。 ただし標準地域コードの著作権者が誰になるのか、統計LODのサイトに 記載が無い…(追記・「政府統計の総合窓口(e-Stat)」で良いそうだ)。

]]>
Wed, 13 Jul 2016 00:00:00 +0900
http://blog.emaita.jp/2016/07/13/standardareacode.html http://blog.emaita.jp/2016/07/13/standardareacode.html <![CDATA[いわゆる市区町村コードなるもの]]> いわゆる市区町村コードなるもの

これまで行政由来のデータを扱うことがほとんど無かったので 「市区町村コード」とかいうものをほとんど知らなかったのであるが、 業務上避けて通れなくなったので、これを機会に真面目に調べることにしたのである。

いわゆる市区町村コードには、実は3系統あって、初心者は混乱する。 というか混乱した。系統ごとに用語が微妙に違うので google で検索に 巧く引っかからなかったりするようだ。

系統間の関係について、調べた中では ここ が解りやすいか。

自治省系コード

正式には「全国地方公共団体コード」の「都道府県コード及び市区町村コード」。 旧自治省が地方自治体の事務処理のために作成したもので、作成時期は 3系統の中で一番古く、1968年。以下「市区町村コード」と呼ぶ。

「全国地方公共団体コード」は「市区町村コード」の他に 「一部事務組合等コード」が含まれている。この「一部事務組合等コード」が どういうものかと言うと、 たとえば「常総地方広域市町村圏事務組合」のような団体に 事務処理用コードを割り当てるためのものだ。 今回はこのような組合のことは関係ないので立ち入らないことにする。

「市区町村コード」のコードとしての特徴は、

  • 検査数字を含めた 6桁の数値
  • 都道府県、市町村、特別区(東京23区)、政令指定都市の行政区、を収録 (郡、支庁・振興局は除外)

現在は総務省地域力創造グループが管理しており、 総務省の電子自治体のページ から PDF と Excel がダウンロードできる。

過去の情報は、2005年4月1日以降の改正分が同じく PDF と Excel で入手できる。 それ以前の情報について、直接問い合わせところ、総務省地域力創造グループでは データを持っておらず、別途資料を当たられたい、とのことで、 例として 第一法規(という出版社)「全国都道府県・市区町村コード」 を紹介された。

行政管理庁系コード

正式には「統計に用いる標準地域コード」。 旧行政管理庁が 1970年に策定したもので、現在は総務省統計局が管理している。

コードの割り当て規則は、先行の自治省系コードのものを流用しているので、 実態としてはほとんど同じと言って良いが、細かいところで差異がある。

  • 検査数値なしの 5桁
  • 郡、支庁・振興局にもコードを割り当てている。
  • 策定の時点で「削除」扱いになっているコードがある。つまり、 1970年4月1日以前に存在し、先行の自治省系コードが割り当てられていた自治体が、 1970年4月1日までに廃止された場合、自治省系コードとの整合性のため、 そのコードを削除扱いにした、ということ。

電子情報としては、 総務省ウェブサイトの統計部門のページ から PDF, CSV で入手できるが、 2016年3月31日に LOD形式で公開された ので、現在はこれを使うのが良い。 1970年4月1日から現在までの変遷が追跡できる(ただし、一部に誤りがある。後述)。

このページ の一番下に turtle 形式のファイルが置いてある。

JIS コード

正式には JIS X401, JIS X402。 自治省系「市区町村コード」を流用して JIS 規格化したもの、のようだ。 これについて調べる前に、「標準地域コード」の LOD が見付かったので、 調べるのを止めてしまった。

(続く)

]]>
Wed, 13 Jul 2016 00:00:00 +0900
http://blog.emaita.jp/2016/05/25/pymdb.html http://blog.emaita.jp/2016/05/25/pymdb.html <![CDATA[Python で MS Access データファイルを読む]]> Python で MS Access データファイルを読む

mdbtools, pymdb を使えば Python 上から MS Access のデータファイルが 読めるらしい、と知った。こういうものがネットに転がっているとは 便利な時代になったものである。

Mac だと、MacPorts で glib2 と glib2-dev の切替が巧く行かず、 面倒だったので止めた。

従っていつも通り FreeBSD 上で実行した。10.3 Release。

mdbtools

mdbtools は MDB ファイルを CSV に変換したりするコマンド群とそのライブラリ。 PKG に収録されているので素直にそれをインストールする。

pkg install mdbtools

mdbtools のコマンドで MDB から CSV に変換できるので、 これだけで充分と言えば充分なのだが、やはり直接 Python 上で 扱えた方が便利なので(値にカンマが混じっていたりして クォーテーションされると面倒)、pymdb も入れる。

pymdb

pymdb は mdbtools の Python 用バインディング。PyPi にある。 pip でのインストールは、少なくとも FreeBSD 10.3R 上では不具合が発生した。

  • glibconfig.h が見つからず、ビルド失敗。

    FreeBSD 10 では glibconfig.h は

    /usr/local/lib/glib-2.0/include/glibconfig.h
    

    にあるが、これが pymdb のサーチパスに入っていない。 glibconfig.h 以外の glib 関係のヘッダファイルは

    /usr/local/include/glib-2.0
    

    にあるのに、何故か glibconfig.h だけ別のディレクトリに設置されている。 何故だろう。よく解らない。

    これを解決するだけだったら /usr/local/include とかに glibconfig.h を 無理矢理コピーすれば pip install が通るが、 次の不具合もあるので二度手間になる。

  • libiconv が無視される。

    pymdb の Cコード上で HAVE_ICONV というマクロが検査されるのだが、 pip install では OS 上に libiconv があるのにも関わらず HAVE_ICONV が セットされない。結果として MDB 内の日本語データが文字化けする。

    解決法は、pymdb の setup.py でマクロを定義して、直接ビルドする。

結論として、setup.py に以下の2行を追加する。

define_macros=[("HAVE_ICONV", "1"),],        # 追加
include_dirs=[
    "/usr/local/lib/glib-2.0/include",       # 追加

pymdb の使用感

pymdb の機能は極めて単純で、MDBファイルの中身を

{ table_name: { "headers": [header_list], "data": [[data_row], ...] }, ...}

という構造に変換するだけである。pythonic に利用するにはラッパクラスを作って __getitem__ 等を書くのが良い。例えば、

class MDBRow:
  def __init__(self, header, row, table_name=None, row_idx=None):
    self.headers = header
    self.data = row
    self.table_name = table_name
    self.index = row_idx
    self.extra_data = {}

  def __getitem__(self, col_name):
    try:
      return self.data[self.headers.index(col_name)]
    except ValueError:
      return self.extra_data[col_name]

  def __setitem__(self, col_name, col_data):
    try:
      self.data[self.headers.index(col_name)] = col_data
    except ValueError:
      self.extra_data[col_name] = col_data
]]>
Wed, 25 May 2016 00:00:00 +0900
http://blog.emaita.jp/2016/04/04/r_wfs2.html http://blog.emaita.jp/2016/04/04/r_wfs2.html <![CDATA[RからWFSを利用する(2)]]> RからWFSを利用する(2)

(承前)

ogr2ogr で保存した GMLファイルを R 上に読み込んでみよう。 それには readOGR を用いる。

R の GIS データ用クラスはジオメトリ型ごとに異なっているらしい。 型ごとに別のオブジェクトに格納する。

> library(gdalUtils)
> library(rgdal)
> pnt <- readOGR("test.gml", "mylayer", require_geomType="wkbPoint")
> lines <- readOGR("test.gml", "mylayer", require_geomType="wkbLineString")
> poly <- readOGR("test.gml", "mylayer", require_geomType="wkbPolygon")
> plot(pnt)

R オブジェクトのクラス名はそれぞれ SpatialPointsDataFrame, SpatialLinesDataFrame, SpatialPolygonsDataFrame のようだ。 plot() に渡すと点や線が表示される。

ローカルファイルに保存せずに R に取り込む

readOGR のデータソースに WFS の URL を指定すれば、WFS サーバから データを直接 R 上に取り込むこともできる。

> mypoints <- readOGR("WFS:http://hogehoge/wfs?version=1.0.0&request=getfeature&typename=mylayer&srsname=EPSG:4326", "mylayer", require_geomType="wkbPoint")
> plot(mypoint)

SpatialPointsDataFrame 等のクラスがどの程度汎用的なのかは 今の私には判らない。ただローカルに GML形式で保存できさえすれば 後はなんとでもなるだろう。

]]>
Mon, 04 Apr 2016 00:00:00 +0900
http://blog.emaita.jp/2016/04/04/r_wfs.html http://blog.emaita.jp/2016/04/04/r_wfs.html <![CDATA[RからWFSを利用する]]> RからWFSを利用する

R で地理データを扱う時に、WFS から直接取り込むことができたら便利に違いない。 幾つか方法があるのかも知れないが、google でまず GDAL を使う方法が ヒットしたので試してみる。

gdalUtils と rgdal というパッケージを使うのだが、実態は、GDAL のコマンドを 呼び出すラッパーのようなので、先に直接コマンドを実行してみる。

さて、まず判り難かったのが、GDAL で WFS ドライバをビルドするには configure で curl オプションを有効にしなければならないということ。 OSX の macports、および FreeBSD の pkg で素直にインストールすると curl は有効になっていないので WFS が使えない。 macports では次のようにする。

$ sudo port install gdal +curl

FreeBSD では ports でリビルドしなければならないので少々面倒臭い。

curl オプション付きで GDAL をインストールすると、ogrinfo で WFS のメタデータを取得できるようになる。以下で利用可能なレイヤの一覧が出力される。

$ ogrinfo "WFS:http://hogehoge/wfs?service=wfs&version=1.0.0&request=GetCapabilities&srsname=EPSG:4326"

ogr2ogr で WFS から取得した GIS データをローカルファイルに保存できる。 TypeName に欲しいレイヤ名を、 request は GetFeature にする。 なお、元データにマルチバイト文字があるとエンコードエラーが出るのと、 線とポリゴンが含まれているとジオメトリ変換エラーが出る。 どちらも、デフォルトの出力フォーマットが shp であることが原因のようだ。 前者は -lco オプションでエンコードを指定して回避する。 後者は、shp がそもそも複数のジオメトリ型をひとつのファイルに 共存させられないから回避できない(処理するジオメトリ型を明示的に指定して 複数回実行するしかない)。出力フォーマットはオプションで 変更可能だが、まずはエラーを無視するように -skipfailures を指定してみる。

$ ogr2ogr test.shp "WFS:http://hogehoge/wfs?service=wfs&version=1.0.0&request=GetFeature&typename=mylayer&srsname=EPSG:4326" -lco "encoding=utf-8" -skipfailures

出力フォーマットは -f オプション で指定する。GML だとエンコーディング問題も 複数型共存問題も生じない。

$ ogr2ogr test.gml "WFS:http://hogehoge/wfs?service=wfs&version=1.0.0&request=GetFeature&typename=PlotNet:plots&srsname=EPSG:4326" -f gml
]]>
Mon, 04 Apr 2016 00:00:00 +0900
http://blog.emaita.jp/2016/03/29/qgis_osx.html http://blog.emaita.jp/2016/03/29/qgis_osx.html <![CDATA[QGIS on OSX 10.9]]> QGIS on OSX 10.9

OSX 10.9.5 に QGIS を入れてみようとして、 まずは MacPorts を試してみたが、ビルドに失敗する。 ログを見ると、system というコマンドを実行しようとして失敗しているようだが、 そのような名前のコマンドは、ユーザランドにも bash built-in にも (libclang にも?)見当たらない。どういうことだ? なお FreeBSD には system(3) がある。

さくらインターネットの個人サーバ(FreeBSD)に pkg で入れて、 X11 Forwarding で使おうかと思って試してみたが、やはり反応が遅くて気が滅入る。 仕方ないので http://www.kyngchaos.com/software/qgis からビルド済み dmg を 落として入れることにした。こういう時にはいつも何故か何かに負けたような 気分になる。

さて入れてはみたが、QGIS の使い方を全然知らないんだよな。 取り敢えず本買うか。

]]>
Tue, 29 Mar 2016 00:00:00 +0900
http://blog.emaita.jp/2016/03/15/gml.html http://blog.emaita.jp/2016/03/15/gml.html <![CDATA[GISデータとGML]]> GISデータとGML

環境省・水環境総合情報サイト、というものがある。 Google で検索した時、 http://www.env.go.jp/water/mizu_site/ が 先頭に出てくるのだが、このサイトに行ってメニューをクリックすると、 Network Error という画面が出てくる。 始めのうちは、何だよメンテでもしてんのか、と思ったが、それらしい 素振りもないし、どうも変だなー、と頭を悩ませていた。

実はこのサイトは古いサイトで、現在ではリニューアルされて https://www2.env.go.jp/water-pub/mizu-site/ で公開されている、 ということに気付くのに半日くらい掛かった。 うーん。自動転送するように設定しておいてくれないものか。

まぁそれはそれとして、このサイトでは、水質調査のデータを ダウンロードすることができる。のだが、Safari だとダウンロードが途中終了する。 サイトのヘルプを見ると、IE のバージョン 8 以上が推奨だそうで、 うへぇ、と思いつつ試しに Firefox 31.0 でやってみると、 無事にダウンロードすることができた。

さて、この ダウンロードページ では、(底質データ以外は)ファイル形式として CSV, SHP, GML を選ぶことができる。 GML についてあまり知識が無かったので、GML って KML の親戚だっけ? などと考えつつググり、OGC 発で ISO 19100 シリーズに取り込まれたことや、 国土地理院が JPGIS という国内規格に取り込んだことなどを勉強した。 ISO 19115/19139 や JMP のことは以前に勉強したことがあって知ってたんだけど、 ISO 19136, JPGIS は聞いた記憶が無いな。なんでだろう。

話を戻して、水質データの中身だが、まず面食らうのが項目名の表記法で、 安直なローマ字表記が妙に笑える。例えば ( 公共用水域水質データファイル利用説明書 より引用)

カラム名 内容
TORIKUROROECHIREN トリクロロエチレン
SIENKATANSO 四塩化炭素
ZETTAICODE 絶対番号

と、中々のセンスである。

まぁカラム名はただのラベルなので本質的にはどうでもいい。

ダウンロードした GML ファイルの中身を見て判ったのは、どうもこのファイルは ツールを使って自動的に生成したものらしい、 ということ。GML ファイル内に http://www.safe.com/gml/fme という URI が 指定されていたので調べたところ、 Safe Software という会社が FME というデータフォーマット変換ツールを売っているようだ。 おそらく環境省から業務を受託した業者が FME を導入したのだろう。 ファイルダウンロード時に十数秒待たされる挙動から、どうも、ダウンロード用ファイルは 事前に用意されているのではなく、その都度マスターDBから生成している 雰囲気がある。

GML は主題情報用のタグなどを別途定義しなければならないため、 この GML形式水質データにも XML スキーマファイルが同梱されている。 しかしこれが如何にも自動生成されましたという顔をしており、 annotation や description が一切無く、maxLength や minOccurs などの 形式面の定義だけが羅列されているという物。 また GML ファイルの方には gml:featureMember というタグが使われているが、 これは GML 3.2.1 では deprecated とされていて、使うべきではない。

という訳で、このサイトの GML形式データは総じてやっつけ感が隠せない仕上がりであった。

参考までに、国交省・国土数値情報のサイトから GML 形式データをひとつ ダウンロードして中身を見てみたが、さすがにこちらは出来が良い。 思いがけず、環境省と国交省の差を見せつけられた一日となった。

]]>
Tue, 15 Mar 2016 00:00:00 +0900
http://blog.emaita.jp/2016/03/11/cc4nonwork.html http://blog.emaita.jp/2016/03/11/cc4nonwork.html <![CDATA[非著作物とCC]]> 非著作物とCC

昨日は NIMS で開催された「オープンサイエンスと著作権」というセミナーに 行ってきた。もちろん会場から質問する機会はあったのだが、その時には 思いつかず、自宅に帰ってきてから何時間も経ってから訊くべきことに 気付く、というよくある事態に。

データは、法的には著作物ではない。 一方で、研究データを CC ライセンスの下で公開する事例が出始めている。 そこで、著作物を前提にして設計されている CC ライセンスを、 著作物ではない研究データに適用することは適切なのか? という疑問が生じる。

  • 法的枠組みとして妥当なのか?
  • 実際問題としてこれは上手いやり方になっているのか?

という点について、弁護士としての見解をお尋ねしたい。

]]>
Fri, 11 Mar 2016 00:00:00 +0900
http://blog.emaita.jp/2016/03/10/license3.html http://blog.emaita.jp/2016/03/10/license3.html <![CDATA[ライセンス色々(3)]]> ライセンス色々(3)

CCAFS GCM Data Portal

国際的な食料安全保障に関するパートナーシップとして CGIAR (Consortium of International Agricultural Research Centers) というものがあるらしく、その中の研究プログラムに CCAFS (Climate Change, Agriculture and Food Security) というものがあり、 その下に Downscaled GCM Data Portal というサイトがある。 世界各地の GCM 研究グループのモデル出力を集めてアーカイブしてある サイトのようだ。ただ、メタデータは用意してないようで、見当たらない。 データファイルのファイル名から内容を推測するしかないようだが、 GCM の専門家でないと内容が理解できないだろう。

それはともかく、ライセンスとしては

  • 再配布禁止
  • 謝辞

という条件だが、それよりもファイルのダウンロード時の対応が面白い。 利用状況把握のために氏名等の情報を教えて欲しいが、嫌なら スキップしてくれてもいいよ、というような文面になっている。 試しに skip をクリックしてみると、確かに何も入力しなくても ファイルのダウンロードができた。

http://ccafs-climate.org/ のダウンロードフォームより引用:

Terms and conditions

To continue downloading your files, please first fill in your email and then some basic information. This information will be used by CCAFS solely for impact assessment and CGIAR and Center level reporting purposes. Filling it in will greatly help us to track the use of the portal and keep improving it. This portal provides data to a very large community of users and improving its usability and efficiency is a key aspect we work on continuously. However, you may click on skip to download links directly.

この設計には好感が持てる。個人的に。

ちなみにこのシステムは Amazon でホストしているらしい。 Amazon の利用料が如何程なのか興味がある。

]]>
Thu, 10 Mar 2016 00:00:00 +0900
http://blog.emaita.jp/2016/03/09/license2.html http://blog.emaita.jp/2016/03/09/license2.html <![CDATA[ライセンス色々(2)]]> ライセンス色々(2)

NCAR EOL

米国 National Center for Atmospheric Research の Earth Observing Lab. の データポリシー 。 後半部の ACKNOWLEDGEMENTS AND PUBLICATIONS にユーザ向けのことが書いてある。

  • EOL への謝辞
  • 個々のデータセットの引用(2個の DOI を含む文字列)

両方の条文に expect という動詞を使用している。

要点として、実際に利用したデータセットだけでなく、それをホストしている EOL という組織に対する謝辞も入れるように要求しているところがひとつ。 ふたつには、DOI が2個あるところで、ひとつはデータセットの最終バージョンに 付けられた DOI で、もうひとつは、データ収集のためのプラットフォームに 与えられた DOI だという。後者はおそらく、研究プロジェクトの開始時に 専用ストレージやポータルサイトのようなものが作成されて、そこに データファイルを集めるような体制になっていて、それに DOI が付けられている ということなのではないかと思う。

]]>
Wed, 09 Mar 2016 00:00:00 +0900
http://blog.emaita.jp/2016/03/08/license.html http://blog.emaita.jp/2016/03/08/license.html <![CDATA[ライセンス色々]]> ライセンス色々

SOCAT

SOCAT は海洋表面CO2 観測データの集積データセット。

利用条件は license や agreement ではなくて statement と位置づけている。 ( Fair Data Use Statement for SOCAT )

そのため、ユーザに対して義務を課すのではなくて “expect” する、という 文面になっている。期待・要求することは具体的には

  1. co-authorship (SOCAT 自体ではなく、SOCAT にデータを提供した個々の研究者に対して)
  2. 引用
  3. 謝辞
  4. バグレポート
  5. 利用して得られた成果の情報提供

SOCAT にデータ提供している研究者は多数であるので、 その全員に連絡を取って共著者として論文を作成するのは大変だ。 そこでガイドラインとして提示されている方法は、 特に大量のデータを提供している研究者には共著の打診を送り、 そうでない研究者には引用と謝辞で済ます、というもの。

全体的に、co-authorship について強く主張する内容になっている。 そんなに拘りがあるなら statement ではなくて agreement にすればいいのに、 と思うが、そうしなかったのは何故だろう。よく解らない。 ちょっと一貫性が取れてないように思える。

気象庁 JRA

気象庁55年長期再解析 のデータ。

利用規約が 利用申し込みのページ にあり、見つけ難かった。内容は、

  1. 氏名、利用目的等の事前申告
  2. 商用利用禁止
  3. 引用
  4. 成果物の提供

1 の事前申告は煩雑に思えるが、まぁ気象庁はお役所だし仕方ないか、とも思う。 しかし、それに加えて許諾の審査があるというのはどうだろう。

申し込み内容を気象庁で検討の上、ID及びパスワードを発行いたします。 ID及びパスワードの発行をもって、共同研究に準じる契約を締結したものと見なします。

一体何を懸念しているのか、にわかには想像できない。

NCEP-DOE Reanalysis 2 では、利用制限は無く、謝辞と成果物提供を(義務ではなくて) お願いするだけになっている。

随分違いがあるなぁ。

]]>
Tue, 08 Mar 2016 00:00:00 +0900
http://blog.emaita.jp/2016/03/07/gcm_license.html http://blog.emaita.jp/2016/03/07/gcm_license.html <![CDATA[GCM データのライセンス]]> GCM データのライセンス

IPCC Data Distribution Centre

というサイトに GCM データの利用規約が記載されている。

AR4 GCM data

出典は ここ

License Statement

These data are licensed for use in Research Projects only. A ‘Research Project’ is any project organised by a university, a scientific institute, or similar organisation (private or public), for non-commercial research purposes only. A necessary condition of the recognition of non-commercial purposes is that all the results obtained are openly available at delivery costs only, without any delay linked to commercial objectives, and that the research itself is submitted for open publication.

研究機関による非商用目的の研究活動に限る、としている。 非商用目的について「得られたすべての成果が公開されること」等々と 明確な定義を与えている。

AR5 GCM data

出典は ここ

CMIP5 Data License Statement

These data were first published under the license of CMIP5. Terms of use for CMIP5 are applied for DDC-AR5 data. They are provided at http://cmip-pcmdi.llnl.gov/cmip5/terms.html. Data from some modelling centres are licensed for use in non-commercial research and for educational purposes, other for unrestricted use. Please refer to the terms of use for the CMIP5 modeling groups for details. DDC-AR5 data should be cited by its DataCite DOI and according to the citation recommendation of CMIP5.

AR5 に使われたデータは CMIP5 なので、CMIP5 のライセンスに従え、とある。 データ提供元に応じて非商用目的限定のデータセットと 制限無しのデータセットがある、とのこと。

Terms of use agreement for CMIP5 model output

出典は ここ

CMIP5 のアーカイブ自体は “non-commercial research and educational purposes” に限定されているが、個々のデータセットで “unrestricted” なものは 制限無しに利用して良い、とのこと。

個々のデータセットの利用条件のリストは これ だが、ほとんどのものは unrestricted で、non-commercial にしているのは 3グループしかない。そして、その3グループはすべて日本のグループである。

  • MIROC: 東大大気海洋研、JAMSTEC、国立環境研究所
  • MRI: 気象庁気象研究所
  • NICAM: 理研計算科学研、東大大気海洋研、JAMSTEC

これはどういう理由だろうか。法令の問題ではないだろうし、研究費の 制限なのだろうか。CMIP のようなプロジェクトで他国と足並みを揃えられないのは かなりまずいような気がするが。いずれにせよ、日本のオープンデータの状況が 遅れているということが現れている。

ライセンスの個々の条文はそれぞれ、

  • a non-commercial の制限について
  • b 免責
  • c 謝辞への記載
  • d DOI の引用
  • e As is 条項(モデルの欠陥など構造的なもの)
  • f As is 条項(QC作業での見逃し)
  • g データ提供者へのフィードバック
  • h 再配布の制限

について記述されている。

]]>
Mon, 07 Mar 2016 00:00:00 +0900
http://blog.emaita.jp/2016/03/04/co_authorship.html http://blog.emaita.jp/2016/03/04/co_authorship.html <![CDATA[公開データの共著者権]]> 公開データの共著者権

今の時代、公開データの利用規約で共著を要求するのは時代遅れだぜ、 ということを説得するための資料収集中。

ICSU-WDS Data Sharing Principles 第3項

All who produce, share, and use data and metadata are stewards of those data, and have responsibility for ensuring that the authenticity, quality, and integrity of the data are preserved, and respect for the data source is maintained by ensuring privacy where appropriate, and encouraging appropriate citation of the dataset and original work and acknowledgement of the data repository.

データとメタデータを生産・共有・利用する人は、すべて、 これらのデータの管理人である。 従ってこれらの人は、以下のことについて責任がある。

  • データの信頼性、品質、完全性が保全されるように保証すること。
  • プライバシー保護が必要な場合は、それを確実にすること。
  • データセットやその元となった作業の適切な引用、 及びデータリポジトリへの謝辞を奨励することによって、 データの出典への配慮が守られるようにすること。

citation, acknowledgement を推奨する一方で co-authorship への言及無し。 典型かな。

]]>
Fri, 04 Mar 2016 00:00:00 +0900
http://blog.emaita.jp/2016/03/03/eml_unit5.html http://blog.emaita.jp/2016/03/03/eml_unit5.html <![CDATA[EMLの単位(5)]]> EMLの単位(5)

(承前)

さてこの L-1 の単位を定義しなければならないのだが、実に悩ましい。 STMML 形式では普通 xxxPerYyy という書き方をするが、perYyy という書き方は しないようだ。

参考までに、 T-1 (周波数)には Hz という固有単位が与えられているので、 これを使って定義している。

<unit id="hertz" name="hertz"
      unitType="frequency" multiplierToSI="1"
      abbreviation="Hz">
  <description>hertz</description>
</unit>

波数には SI の固有単位はないようだ。CGS単位系ではカイザー(K)という単位名が 与えられているらしい。 では波数の定義がどうなっているかと言うと、

<!--waveNumber-->
<unit id="waveNumber" name="waveNumber"
      unitType="lengthReciprocal" multiplierToSI="1">
  <description>1/meters</description>
</unit>

つまり、単位名に物理量の名称を当ててしまっている。これは本当はおかしなことで、 それは SI接頭辞を付けた kiloWaveNumber とか megaWaveNumber という語が 何を言っているのか判らないことから明らかだ。 苦し紛れであることは論を俟たないが、他に記法が無いような気も、確かにする。 kiloParMeter 等とするのもやはりおかしい。

そう言う訳で、結論としては以下のような custom unit を定義した。

<!-- attenuation coefficient (m^-1) -->
<unit id="attenuationCoefficient"
          name="attenuationCoefficient" unitType="lengthReciprocal"
      multiplierToSI="1" abbreviation="1/m">
  <description>Coefficient of exponential attenuation</description>
</unit>

釈然としないところがあるが、どうにもならん。

]]>
Thu, 03 Mar 2016 00:00:00 +0900
http://blog.emaita.jp/2016/03/02/eml_unit4.html http://blog.emaita.jp/2016/03/02/eml_unit4.html <![CDATA[EML の単位(4)]]> EML の単位(4)

指数関数的減衰における減衰係数の単位は対象とする物理現象によって異なるが、 ここではある物質中を電磁波(光線)が通過することを考える。 すると電磁波は物質中を進む距離に応じて減衰するので、この場合は 減衰係数の単位は L-1 の次元になる。

まぁ要するに日射光の減衰である。

この L-1 の次元の物理量は珍しいようで、EML標準の単位定義には 波数しか無い。

<unitType id="lengthReciprocal" name="lengthReciprocal"> <!--waveNumber-->
  <dimension name="length" power="-1"/>
</unitType>

しかも単位の型名として「距離の逆数(length reciprocal)」などという こなれない語句を当てていて、いかにも苦し紛れな感じがする。 そう言われてみると確かに L-1 次元の物理量はにわかには 思いつかない。不思議な感じがする。

ともあれ係数は扱いが難しく、EML標準定義にはほとんど無い。 少ない中のひとつが transmissivity で、 L2 T-1 の次元である。

<unitType id="transmissivity" name="transmissivity"> <!--metersSquaredPerSecond-->
  <dimension name="length" power="2"/>
  <dimension name="time" power="-1"/>
</unitType>

 Transmissivity は地質学では透水量係数を意味するようだが、 生態学にはあまり関係がないように思うので、 拡散係数を表現しているのではないかと思われるが、どうだろう。 分野を限定しないと用語の意味が確定しないのは科学の難点のひとつである。

]]>
Wed, 02 Mar 2016 00:00:00 +0900
http://blog.emaita.jp/2016/03/01/eml_unit3.html http://blog.emaita.jp/2016/03/01/eml_unit3.html <![CDATA[EMLの単位(3)]]> EMLの単位(3)

(承前)

ところで意外なことに EML標準にはエネルギーのフラックスを表す単位が 定義されていない。いや、別に意外ではないのか? よく判らないが、日射フラックスなどを表すのに MJ m-2 h-1 とか W m-2 を使う。 次元を計算してみると M T-3 という不思議な次元になる。

<!-- energy flux -->
<unitType id="energyFlux" name="energyFlux">
  <dimension name="mass" power="1"/>
  <dimension name="time" power="-3"/>
</unitType>
<unit id="joulesPerSquareMeterPerSecond"
  name="joulesPerSquareMeterPerSecond"
  unitType="energyFlux"
  multiplierToSI="1"
  abbreviation="J/㎡/s">
  <description>flux of radiation</description>
</unit>
<unit id="megajoulesPerSquareMeterPerHour"
  name="megajoulesPerSquareMeterPerHour"
  unitType="energyFlux"
  parentSI="joulesPerSquareMeterPerSecond"
  multiplierToSI="277.7778"
  abbreviation="MJ/㎡/h">
  <description>flux of radiation</description>
</unit>
<unit id="megajoulesPerSquareMeterPerDay"
  name="megajoulesPerSquareMeterPerDay"
  unitType="energyFlux"
  parentSI="joulesPerSquareMeterPerSecond"
  multiplierToSI="11.5741"
  abbreviation="MJ/㎡/d">
  <description>flux of radiation</description>
</unit>

今日は一日、高校物理の復習をして過ごしたような気がする。

]]>
Tue, 01 Mar 2016 00:00:00 +0900
http://blog.emaita.jp/2016/03/01/eml_unit2.html http://blog.emaita.jp/2016/03/01/eml_unit2.html <![CDATA[EMLの単位(2)]]> EMLの単位(2)

(承前)

とは言え、他人の仕事の粗探しをしても自分の仕事が進む訳ではないのだ。 自分なりに考えて実装してみると、以下のようになった。

<!-- amount of photons -->
<unitType id="amountOfPhotonFlux" name="amountOfPhotonFlux">
  <dimension name="amount" power="1"/>
  <dimension name="length" power="-2"/>
  <dimension name="time" power="-1"/>
</unitType>
<unit id="einsteinsPerSquareMeterPerSecond"
  name="einsteinsPerSquareMeterPerSecond"
  unitType="amountOfPhotonFlux"
  multiplierToSI="1"
  abbreviation="E/㎡/s">
  <description>Einsteins (mols of photons) per square meter per secound</description>
</unit>
<unit id="microeinsteinsPerSquareMeterPerSecond"
  name="microeinsteinsPerSquareMeterPerSecond"
  unitType="amountOfPhotonFlux"
  parentSI="einsteinsPerSquareMeterPerSecond"
  multiplierToSI="0.000001"
  abbreviation="μE/㎡/s">
  <description>micro Einsteins (10^-6 mols of photons) per square meter per secound</description>
</unit>

molesOfPhoton のように Of を使う用例は EML 標準には少ないので、 素直に einstein を使うようにした。

ところで flux という用語は、 EML標準の単位定義では T-1 の次元に 使われているのだが、私の業界では L-2 T-1 を意味する。 一般にフラックスは「単位時間、単位面積あたりの流量」のことだから、 EML標準の用法がおかしいように思う。 一方で EML標準では rate という用語も T-1 の次元を意味するらしく、 混乱する。 これらの用法は一体どこから来ているのだろうか。よく判らない。

]]>
Tue, 01 Mar 2016 00:00:00 +0900
http://blog.emaita.jp/2016/03/01/eml_unit.html http://blog.emaita.jp/2016/03/01/eml_unit.html <![CDATA[EML の単位]]> EML の単位

EML(Ecological Metadata Language) は 生態学データに特化した規格であるとされているが、 色々と不足がある。中でも、標準で用意されている数値データの物理量の単位が 網羅的でなく、使いたい単位が無い場合も多い。 そういう場合は custom unit を定義して、その定義を EML メタデータに 個々に追加する必要がある。

今回問題となったのは、光合成の研究で使われる光子量の単位で、 例えば μmol photons m-2 s-1 である。 光合成量は光子のエネルギー量ではなくて光子の個数によって決まるため、 ジュール(J)等ではなくて物質量(mol) の単位を使う。 なお、光子 の mol 数を表す単位としてアインシュタイン(E)がある (ということを今回初めて知った)。 従って μmol photons m-2 s-1 は μE m-2 s-1 でもほぼ等価である。

さて、光合成の研究などは世界各地でうんざりするほど実施されている訳で、 そのデータ用の EML メタデータも既に作成されている筈である。 Google で検索してみたところ、早速 2,3 個ヒットした。

Harvard Forest Research の knb-lter-hfr.140.9

<stmml:unit
    name="micromolePerMeterSquaredPerSecond"
    unitType="arealMassDensityRate"
    id="micromolePerMeterSquaredPerSecond"
    parentSI="molePerMeterSquaredPerSecond"
    multiplierToSI="0.000001"
    constantToSI="0.0"
    />

シカゴ大 Marine Biological Lab. の knb-lter-pie.92.3

<unit
    name="microEinsteinPerMeterSquaredPerSecond"
    unitType="illuminance"
    id="microEinsteinPerMeterSquaredPerSecond"
    parentSI="" multiplierToSI="1">

ミネソタ州立大 McMurdo Dry Valleys の knb-lter-mcm.3001.34

<stmml:unit
    id="umolphotons/m2/second"
    name="umolphotons/m2/second"
    abbreviation=""
    unitType="">

フロリダ国際大 FCE サイトの 単位リスト

microEinsteinsPerSquareMeterPerSecond
illuminance
µE/m^2/s
Einsteins (1E-06 moles of photons) per square meter per second (radiant flux density)

定義が 4者4様で興味深いが、どれも間違いがあるのは頂けない。

HFR と MBL はそれぞれ “micromole…” “microEinstein…” としているが、 s を入れて “micromoles…” “microEinsteins…” とするべきだ。

MCM の “umolphotons/m2/second” は STMML 書式ですらない (<stmml:unit> というタグを使用しているのに)。

MCM と FCE は単位のカテゴリを illuminance としているが、 illuminance(照度)は心理物理量で、人間の視覚システムが感じる明るさ、 を意味しており、光子の物理学的なエネルギーや個数とは一意な関係には無い。 また HFR はカテゴリを arealMassDensityRate としているが、 mass は質量(kg, ton など)のことであり、 mol 数は 物質量(amount of substance)である。

EML は custom unit という名目で自由に単位を追加することができるが、 反面、それを正しく使うのにはそれなりの知識が必要で、 正確に記述できるかどうかは担当者の力量に強く依存する。 人間がメタデータを読む分には問題は生じないだろうが、 将来的に機械で自動処理させる段になったら困りそうだ。

]]>
Tue, 01 Mar 2016 00:00:00 +0900
http://blog.emaita.jp/2016/02/09/ccl.html http://blog.emaita.jp/2016/02/09/ccl.html <![CDATA[CCライセンスは何故ソフトウェアには適さないのか]]> CCライセンスは何故ソフトウェアには適さないのか

故あって CCライセンスを調べている時に、クリエイティブコモンズジャパンの FAQ に、 CCライセンスはソフトウェアには使わない方がよい、ということが書いてあるのを見つけた。 どういう理由でそう主張しているのか知りたかったのだが、詳しいことが書いていない。 CCジャパンの FAQ は古いもののようで、本家の FAQ に明らかに追随していないので、 本家FAQ を読んだついでに、備忘のために和訳しておく。

元テキスト

CCライセンスをソフトウェアに適用できるか?

我々は、CCライセンスをソフトウェアに使用しないことを推奨する。 その代わりに、既に利用可能な、非常に出来の良いソフトウェアライセンスのひとつを 使用するように強く奨励する。 FSF が作成したライセンスや、Open Source Initiative が “open source” として リストしているライセンスを検討するようにお勧めする。

ソフトウェア専用のライセンスとは違って、CCライセンスはソースコードの配布という 観点を持っていない(その観点はソフトウェアの自由な再利用と改変を保証するために 非常に重要であることが多いのだが)。 また多くのソフトウェアライセンスはパテント権を扱っている (パテントは、ソフトウェアにとっては重要だが、他の著作物にはあまり当てはまらない)。 さらに、CCライセンスは現在のところ主要なソフトウェアライセンスとは互換ではなく、 従ってCCライセンスの作品と他のフリーソフトを統合することが難しい。 既存のソフトウェアライセンスはソフトウェアに使用することに特化して 設計されており、CCライセンスと似たような権利群を提供している。

CC-BY-SA 4.0 ライセンスは GPLv3 に対して一方向の互換性がある。 この互換性は、コンテンツが、分離も識別もできないような形態で ソフトウェアコードに統合されるような状況のために設計された。 この互換性を利用する前には特別な熟慮が必要だ。詳しくは別項を見よ。

また、CC0 はGPL互換で、ソフトウェアにも適切である。詳しくは別項を見よ。

CCライセンスをソフトウェア自体に使用することは推奨しないが、 ソフトウェアの説明書とか、ゲームアートや音楽などの独立性のある要素には CCライセンスが使える可能性がある。

(ここまで)

解説

CCライセンスがソフトウェアに適さない理由は、主に、 ソフトウェアの実体がソースコードにあるからである。

比較としてイラストを考えると、イラストの複製・再利用を認める場合、 PNG や JPG などの完成品が自由に複製・再利用できれば基本的に充分で、 Photoshop の元データとかまで公開する必要は通常は無い。

しかしソフトウェアは、コンパイル済みのバイナリでは再利用や改変が難しく、 元となるソースコードの公開が必要である(オープンソースというのはまさに そういう意味だ)。

このような構造的な差異があるため、CCライセンスはソフトウェアに適さない、 と主張しているのであろう。

]]>
Tue, 09 Feb 2016 00:00:00 +0900
http://blog.emaita.jp/2015/12/21/latex.html http://blog.emaita.jp/2015/12/21/latex.html <![CDATA[platex + dvipdfmx で日本語フォント埋め込み]]> platex + dvipdfmx で日本語フォント埋め込み

時々思い出したように tex を使うが、その度に色々変わっていて 戸惑っているような気がする。

Mac 附属のヒラギノフォントを PDF に埋め込むための手順を調べた。 基本的に ここここ を参考にしたが、後で混乱しないようにメモしておく。

環境:Mac OS X 10.9 + TeXLive2015(MacPorts)
# mkdir -p /opt/local/share/texmf-local/fonts/opentype/public/hiragino
# cd !$
# ln -s "/Library/Fonts/ヒラギノ明朝 Pro W3.otf" HiraMinPro-W3.otf
# ln -s "/Library/Fonts/ヒラギノ角ゴ Pro W6.otf" HiraKakuPro-W6.otf
# mktexlsr
# updmap-sys --setoption kanjiEmbed hiragino
# kanji-config-updmap hiragino

その上で、dvipdfmx に -f オプションでフォントを指示する。

$ dvipdfmx -f ptex-hiragino.map hogehoge.dvi
../../../_images/hiragino.png

ちなみに -f オプションを指定しないとヒラギノではなくて IPAフォントが埋め込まれた。

../../../_images/ipa.png ]]>
Mon, 21 Dec 2015 00:00:00 +0900
http://blog.emaita.jp/2015/12/10/mooc2.html http://blog.emaita.jp/2015/12/10/mooc2.html <![CDATA[MOOCについて補足]]> MOOCについて補足

前記事を書いた後で CiNii で検索したところ、 船守「デジタル空間に移行する大学教育」情報の科学と技術 65: 258-263, 2015 という文献が見つかった。これには MOOC について興味深いことが記述されており、

  • MOOC の開発費用(教材作成費用?)は1コースあたり 1000-3000万円と高額
  • これに対して学生からは、学費を負担している正規の学生への教育でなく、学外の 不特定多数に無料の講義を提供することに多額の資金を費やす大学側の姿勢に 批判が出ている
  • 大学当局は、MOOC を学内教育にも流用することでこの批判を躱そうとしている (いわゆる反転授業)

そうである。

開発費が 1000-3000万円というのは、想像していたよりも文字通り一桁大きいので 単純に驚いた。既存の講義資料を流用すれば安上がりにできるだろうと思っていたが、 そうではなくて新規に製作しているのか。ならば金も掛かるし、 学生が怒るのも無理はない。

gacoo の教材はどのくらいの予算で作ってんでしょうね。

]]>
Thu, 10 Dec 2015 00:00:00 +0900
http://blog.emaita.jp/2015/12/09/mooc.html http://blog.emaita.jp/2015/12/09/mooc.html <![CDATA[MOOC というものがあったらしい]]> MOOC というものがあったらしい

基本的に時勢に疎い人間なので、 新しい流行について私が初めて見聞きした時には既に その流行は廃れかけていた、ということがよくある。

MOOC (Massive Open Online Course) という言葉を目にしたのは昨日が最初で、 JST の STI Updates に 総務省、データサイエンス・オンライン講座「社会人のためのデータサイエンス入門」を再開講 という記事があったので、そのオンライン講座とやらの内容にちょっと興味が湧いて gacoo のサイト に行ってみた訳である。 レジュメ を見ると、 内容自体はおおよそ初歩的な統計ネタで(平均値の見方、とか)、 私の期待とは違ったのだが、最後の方に「e-Stat の使い方」という項目があって、 私は e-Stat を使ったことがないのでちょっと見てみたい、と思った。

それで、どうやったら中身を見られるのか知るために、 gacoo のシステムや運営 についてサイト内を調べて回ったのであるが、 「開講期間」とか「修了証」とか「相互採点」とか、 意味が理解できない用語が幾つも出てくるので混乱してしまった。 どうも、講義資料が PDF や slideshare みたいな感じで置いてあって、 興味があるところだけ見られる、というようにはなっていないらしい。 中身を見るには、受講手続きして、開講するのを待って、 週一で課題を解いて提出して、最終試験を受けたりしないといけないらしい。

なにこれめんどくさい。と心の底から思った。

gacoo の元締めの JMOOC のサイト に MOOC について解説があって、 そこには「今、世界中で MOOC が流行ってます」といったようなことが 書かれていたが、私にはこんな面倒なものが流行るとは思えず、 不可解な気分になった。

こういう場合は、自分が間違っているのか、それとも世界が間違っているのか、 きちんと調べて理解しなければならない。 自分は正気であると信じている人間は、常に、自分の知性が正常に機能しているか 否かを点検し続ける義務があるからである。

“MOOC” でググったところ、割と上位に TechCrunch の オンライン講義のMOOCが大学に取って代わることができない理由 という記事が出てきて、やはり私の直観通り、MOOC の流行は既に終わっているようだ。

この記事は 2015年5月のものだが、その約1年前、日本国内でも その事実は認識されており、しかもそれが JMOOC の関係筋(放送大学の人) から語られている。 山田恒夫「MOOCとは何か ポストMOOCを見据えた次世代プラットフォームの課題」 情報管理 57(6): 367-375, 2014. DOI: 10.1241/johokanri.57.367 (2014年7月受理、とある)

別の文書によると、2013年後半には既に「MOOC は Hype(誇大宣伝)だ」と 言われ始めたそうである。MOOC が出現したのは 2012年らしいので、 1年くらいは幻想が保ったようだ。 堀真寿美「ポストMOOCと日本の大学経営」ViewPoint 14: 50-52, 2014.

一方で JMOOC 関係者は、MOOC は今でも世界的に拡大していると主張している (2015年5月の記事)。 MOOCの広がりと登録者12万人のgaccoの取り組み これが本心からの言葉か、立場上の発言なのかは判別できない。

MOOC の対極に SPOC (Small Private Online Course) があるが、 MOOC よりも SPOC の方に注目している人も出てきている。 荒木博行「オンライン教育でリーダーは育つか?」 マネタイズや学習効果という点では確かに SPOC の方が有利だろう。

上記荒木氏によると、MOOC の関係者ももはや Massive や Open に あまり拘らずにサービスを変容させて行き詰まりを乗り越えようと しているそうである。 荒木博行「MOOCは儲かるのか?」 「「MOOC」という呼び名が過去のものになるのも時間の問題かもしれません。」 と書かれているが、私もそんな気がする。

さて、私の MOOC に対するイメージは gacoo サイトを見た印象から得たものだが、 gacoo/JMOOC と本場の MOOC は質的にまったく異なるという意見もあるようだ。 tkyon「MOOCを利用し始めて1年が経過した」 これを読むと、gacoo を見ただけで MOOC について解ったような気になっては いけないらしいことが理解できる。少なくとも本場の MOOC には 高等教育に対する高い理想があるんだな。

]]>
Wed, 09 Dec 2015 00:00:00 +0900
http://blog.emaita.jp/2015/12/03/orcid.html http://blog.emaita.jp/2015/12/03/orcid.html <![CDATA[ORCID ID を作ってみた]]> ORCID ID を作ってみた

何ヶ月も前から、試しに ORCID ID を取得しなければ、とは思ってはいたが、 目先の仕事以外のことはしたくない、という生来の面倒臭がりのために放置していた。 PlotNet のデータ入力に飽きたので気分転換に ORCID のサイトに アクセスしてみた。登録自体は簡単で、確かに5分もあれば済む。 認証メールは一応送られては来るが、 メール認証しなくても先に進むことができるので、逆にそれで 大丈夫かと心配になるくらいだ。 メール認証を放置すると後で取り消しになったりするのかしら。

ひとつ感心したのが、パスワード入力欄のヘルプに、パスワード文字列で 使用可能な記号文字をきちんと明記してあるところだ。

../../../_images/orcid_pass.png

私は普段、パスワード用文字列を乱数生成するのに apg というツールを使っている。

mac:~$ apg -h

apg   Automated Password Generator
        Copyright (c) Adel I. Mirzazhanov
(snip)
mac:~$ apg -a 1
>~B"Av~qJ1
$xphcK~qO/
kbUX8Kp`Ke
\hX?,LQ$
nlZ#2'pQ6
z"~1TtF(M

apg は ‘” とか <> とかの記号を遠慮なく混ぜてきて、パスワードの強度としてはいいのだが、 これをそのまま入力フォームにコピーすると、時々、エラーを吐くサイトがあって、 面倒臭い。使用可能文字に制限があるなら先に書いておくべきであろう。 こちらとしては、なるべく強度の高い文字列を選んで使おうとしているのに、 それがエラーとなると、恩を仇で返されたような気分になるのである。

私の ID は 0000-0002-3987-2098 になった。

勤務先情報の入力などもあっと言う間に終わってしまい、拍子抜けしたので、 遊びで自分の姓を検索してみた。

../../../_images/orcid_search.png

結果は 7件。大半がラテン系と思われる人名だが、中にひとり、「まいたひろし」という いかにも日本人っぽい名前の人物が居た。名前以外の情報は未入力か非表示にしているようで、 どこの誰だかは ORCID 上では判らない。

CiNii で検索すると、米田宏(バイオ系)と米田広(流体工学)という人物が出てきた。 「米田」を「よねだ」ではなく「まいた」と読ませる姓が存在することは前から知ってはいたが、 ふたりも出てくるとは思わなかった。 おそらくこのうちのどちらかが ORCID に登録したのであろう。どちらなのかは 情報不足で判らない。おそらく、私がそれを知る機会は無いだろう。

]]>
Thu, 03 Dec 2015 00:00:00 +0900
http://blog.emaita.jp/2015/12/03/nemopilema_nomurai.html http://blog.emaita.jp/2015/12/03/nemopilema_nomurai.html <![CDATA[KNB にエチゼンクラゲ]]> KNB にエチゼンクラゲ

ここしばらくの間ずっとデータ入力に掛かり切りで、世間の動向に無関心で過ごした。 今日あたり東京で IDF の会議があるはずだが、申し込みとかすっかり忘れていて、 まぁいいか別に俺は行かなくて、と思うことにした。

EML ソフトウェアがバージョンアップされてないか、と思い、 久しぶりに KNB のサイトに行ってみた。 数ヶ月前は、確か、証明書関係のエラーが出て接続できなかったような気がするが、 今日行ってみたところ、普通に表示された。直ったのか、記憶違いか。

ソフトウェアの新バージョンは無かったが、 データベースの中に日本のデータセットが3件あるのに気付いた。 漁業情報サービスセンターのエチゼンクラゲのデータのようで、 3件とも中身は同じようだが何故かメタデータは 3件登録されている。 よく解らない。

どういう経緯で登録されたのか。 メタデータの中に “Usage restricted to Global Jellies Working Group members.” と書いてあって、ググってみると NCEAS かどこかがクラゲのデータベースを作ってるらしく、 その関係で日本が取っている日本周辺のデータを提供したもののようだ。

しかしいつの間にか KNB のデータベースに DOI が導入されているね。 このクラゲデータセットにも DOI 付いてるし。 金があるところは色々出来ていいなぁ。

]]>
Thu, 03 Dec 2015 00:00:00 +0900
http://blog.emaita.jp/2015/09/24/jdc_flaw.html http://blog.emaita.jp/2015/09/24/jdc_flaw.html <![CDATA[JDC の不具合]]> JDC の不具合

先週の JaLTER DB 講習会で発覚したのだが、 IE 11 では JDC のファイルアップロード機能が上手く動作しない。 同じ PC 上で Chrome で操作すると動作するので、OS ではなく ブラウザが原因なのだろう。

手元に IE 11 が動作する PC が無く、原因究明ができないため、 差し当たり他のブラウザを使用して頂きたい。

]]>
Thu, 24 Sep 2015 00:00:00 +0900
http://blog.emaita.jp/2015/09/24/trdci.html http://blog.emaita.jp/2015/09/24/trdci.html <![CDATA[TR DCI 続報]]> TR DCI 続報

JaLTER DB に格納されているデータセットの一部について、 そのメタデータをトムソンロイター社の Data Citation Index に提供するという件、 結局メタデータは ftp で送るということになり、6月に送信してあった。

その後、向こうでどのような作業が進んでいるのかまったく音沙汰が無かったのだが、 先日、TR DCI の “Master Data Repository List” を検索してみたら、 JaLTER DB が登録されているのを発見した。

../../../_images/dci_repo.png

9月頭に調べた時には発見できず、9/14 に調べた時にはヒットしたので、 その間の約 2週間の間に登録されたようだ。6月にメタデータを送ってから 9月まで、一体何に時間が掛かっていたのか、よく解らないが、 ともかく向こうの作業が進んでいるようなので安心した。

本来なら DCI そのものを検索して、JaLTER DB のレコードが登録されているか どうか確かめたいのだが、以前に記述したように、NIES では DCI を契約していない ので私が直接確かめる方法が無い。伝手を辿ってみるか…

しかしそれにしても、JaLTER DB の Responsible Organization として 日本生態学会が記載されているのはどうしたものか。向こうとしては、 JaLTER のような、永続性に不安がある組織よりも、学会のような 社会的・財政的に確立された組織の方が好ましい、ということなのだろうか。 この点は後で検討した方がいいかも知れない。

]]>
Thu, 24 Sep 2015 00:00:00 +0900
http://blog.emaita.jp/2015/08/26/fileapi.html http://blog.emaita.jp/2015/08/26/fileapi.html <![CDATA[FileReader 追記]]> FileReader 追記

JDC に投入したデータを遡って調査したところ、壊れたファイルが見つかったので 再投入した。

調査の過程で解ったことは、2014年4月まではファイル破損がなく、 2015年4月から破損が生じていることである。このことから、 2014年4月後半に端末の MacBook を買い替えたことがエラー顕在化の 原因と推定される。

以前に使用していた MacBook は 2009年に購入したもので、性格が貧乏性のため 2014年まで使っていた。OS も Leopard のまま、アップグレードせず。 おそらく、Leopard の Safari には FileAPI が実装されていなかったのだろう。 ネットで拾った JavaScript コードは、 FileReader が実装されていればそれを使い、 実装されていなければファイルを直接読む、というようなロジックが組まれていたので、 前の MacBook で開発している時には FileReader.readAsBinaryString() が 実行されていなかったのだと思われる。そのため開発中ずっとこのバグに 気がつかなかった、ということなのだろう。

盲点だった。古い環境を使い続けるのも考えものだな。

これで少なくとも、私が JDC 開発中にバグに気付かなかった原因は解った。 しかし他の人々が FileReader.readAsBinaryString() の挙動を誤解していた (している?)原因はやはり不明である。

]]>
Wed, 26 Aug 2015 00:00:00 +0900
http://blog.emaita.jp/2015/08/25/readasbinarystring.html http://blog.emaita.jp/2015/08/25/readasbinarystring.html <![CDATA[FileReader.readAsBinaryString は Binary を返さない]]> FileReader.readAsBinaryString は Binary を返さない

JDC にバグが見つかった。zip ファイルをサーバにアップロードすると、 ファイルが壊れるというものだ。テスト用インスタンスを立ち上げて 挙動を見てみると、サーバ側ではなくクライアント側でファイルが壊されているようだった。 具体的には、ファイルサイズが何故か 1.5 倍に増加しており、しかも、データが ランダムなバイト列ではなく UTF-8 にエンコードされているのであった。

ファイルのアップロードにはネットで拾ったパプリックドメインの JavaScript コードを 利用していて、これがファイルの読み込みとサーバへの送信を実行している。 読み込みから送信までの間に何かが起こっているのだろう、とはすぐに見当がついた。 処理を追いかけて調べた結果、FileReader.readAsBinaryString() が読み込んだ ファイル内容を破壊していることがわかった。 これを FileReader.readAsArrayBuffer() に変更することでバグ自体は 修正できたのだが、これについて調べた結果がやや興味深かったので記録しておく。

さてこの FileReader.readAsBinaryString() 、字面からは、バイナリファイルを 読み込んで中身のバイナリデータをメモリ上に保持する函数であるかのように見える。 ネット上の記事でもそのように解説されているものが多いようだ。 たとえば これ とか これ とか これ とか。

ところが、実はそうではない。 FileReader.readAsBinaryString() は仕様上 DOMString オブジェクトにデータを 格納することになっており、そして DOMString は UTF-8 しか受け付けない。 だから、少なくとも仕様上は、 FileReader.readAsBinaryString() は ランダムなバイト列を読み込むことはできないのである。 ( 参考

そのため、たとえば Safari のエンジンである WebKit ではどうなっているかと言うと、

Source/WebCore/fileapi/FileReaderLoader.cpp:295
    switch (m_readType) {
    case ReadAsArrayBuffer:
        // No conversion is needed.
        break;
    case ReadAsBinaryString:
        m_stringResult = String(static_cast<const char*>(m_rawData->data()), m_bytesLoaded);
        break;

ReadAsArrayBuffer ではデータに何も加工しないのに対して ReadAsBinaryString では String クラスに渡す。この String には コンストラクタが数種類定義されているが、この場合に呼ばれるのは、

Source/WTF/wtf/text/WTFString.h:84-
    class String {
    ..snip..
    // Construct a string with latin1 data.
    WTF_EXPORT_STRING_API String(const LChar* characters, unsigned length);
    WTF_EXPORT_STRING_API String(const char* characters, unsigned length);

の下の方である。コメントに書かれているように、入力データを latin1 として 強制的に解釈する。そして target.result に結果を格納する際に UTF-8 に変換する のであろう。

実際、サーバに送信された壊れたデータを取り出して、元のファイルと比較してみると、

iconv -f L1 -t UTF-8

と変換した場合にファイルサイズも内容も一致した。

この FileReader.readAsBinaryString() 、実は 2012年に W3C の仕様から 削除されている。 2011年の仕様 では、 代わりに readAsArrayBuffer() を使うようにと書かれている。 その理由は、 readAsBinaryString() が、readAsBinaryString という名称でありながら DOMString の制限のためにバイナリを返せないという中途半端な函数だったからだろう。

それにしてもよく解らないことがある。

まず、多くの人が、readAsBinaryString() はバイナリファイルの内容をそのまま 保持する函数だと思っていたことである。 ざっとググった限りでは、そうではないと書いてある日本語ページは ここ くらいである。

もしかしたら、以前のブラウザの実装は、W3Cの仕様に反して、内容を加工しない ようになっていたのかも知れない。何しろわたしも JDC の開発中にこのことに 気がつかなかった。しかし WebKit のリポジトリから 2011年頭頃のコードを 取り出してみたが、今現在と変わらないように見える。 他の webエンジンではどうなのだろうか。

]]>
Tue, 25 Aug 2015 00:00:00 +0900
http://blog.emaita.jp/2015/07/28/formalchemy.html http://blog.emaita.jp/2015/07/28/formalchemy.html <![CDATA[FormAlchemy のカスタマイズ]]> FormAlchemy のカスタマイズ

FormAlchemy には PostgreSQL の範囲型や配列に対応する renderer が 用意されていない。しかしコードを読んだらカスタマイズはそれほど 難しくはなさそうだったので書いてみた。

要点は、 formalchemy.fields.FieldRenderer をベースにして render(), render_readonly(), deserialize() 等をオーバーライドする。 フォーム出力用に formalchemy.helpers.text_field() というヘルパー函数が 用意されているため、これを利用すれば手間が省ける。 deserialize() はフォームの入力内容をパースする時に呼ばれるメソッドで、 入力内容を解釈して適切な Python オブジェクトに変換する機能を持たせる。

init4range と array 用のコードは以下のようになる。 これを forms.py に追加する。

from formalchemy import FieldSet
from formalchemy.helpers import text_field
from sqlalchemy.dialects.postgresql import INT4RANGE, ARRAY
from formalchemy.fields import FieldRenderer
from psycopg2.extras import NumericRange

class Int4RangeRenderer(FieldRenderer):
  def _range_string(self):
    # self.value は u"NumericRange(115, 889, '[)')" という文字列になっている
    # self.raw_value に NumericRange インスタンスがあるのでそれを利用
    # PostgreSQL 内には "[lower, upper+1)" という形式で格納されるようだが
    # 解り難いので "[lower, upper]" という形式で入出力する
    if isinstance(self.raw_value, NumericRange):
      value = "[{},{}]".format(self.raw_value.lower, self.raw_value.upper-1)
    else:
      value = ""
    return value

  def render(self, **kwargs):
    return text_field(self.name, value=self._range_string(), **kwargs)

  def render_readonly(self, **kwargs):
    return self._range_string()

FieldSet.default_renderers[INT4RANGE] = Int4RangeRenderer


class ArrayRenderer(FieldRenderer):
  def render(self, **kwargs):
    value = " ".join(self.raw_value)
    return text_field(self.name, value=value, **kwargs)

  def deserialize(self):
    # スペース区切りの文字列として受け取る
    data = self.params.getone(self.name)
    data = data.split()
    return data

FieldSet.default_renderers[ARRAY] = ArrayRenderer

FormAlchemy の設計では配列型の中身のデータ型に応じて default_renderer を切り替えるようにはできないので、上記コードでは 配列型を一緒くたに扱っている。

]]>
Tue, 28 Jul 2015 00:00:00 +0900
http://blog.emaita.jp/2015/07/27/pyraid4.html http://blog.emaita.jp/2015/07/27/pyraid4.html <![CDATA[Pyraid + GeoAlchemy2 + GeoFormAlchemy2 (4)]]> Pyraid + GeoAlchemy2 + GeoFormAlchemy2 (4)

(承前)

次に、GeoAlchemy2 を使ってジオメトリデータを PostGIS に投入する方法を確認する。 簡単のため、Pyramid + GeoFormAlchemy2 は使用せずにロジックだけ追う。

モデルは以下とする。

class Plot(Base):
    __tablename__ = 'plots'
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    geom = Column(Geometry('geometry', 4612))

作成するジオメトリは、複数の POINT を含むコレクションで、 以下をサンプルデータとする。

dat = [ [6,8], [8,1], [9,44] ]

ジオメトリのオブジェクトは shapely のものを利用する。

from shapely.geometry.point import Point
from shapely.geometry.collection import GeometryCollection
points = []
for i in dat:
  points.append(Point(i))
gc = GeometryCollection(points)

この時点で、例えば gc.to_wkt() とすると

GEOMETRYCOLLECTION (POINT (6.0000000000000000 8.0000000000000000), POINT (8.0000000000000000 1.0000000000000000), POINT (9.0000000000000000 44.0000000000000000))

が得られ、PostGIS に投入可能のように見えるが、残念ながらそうではなく、 SRID が指定されていない、とエラーが出る。

そこで、 GeoAlchemy2 の from_shape() を使用する。これは shapely オブジェクトを GeoAlchemy2 のオブジェクトに変換する函数だが、 SRID 情報を付加することができる。

from geoalchemy2.shape import from_shape
geo = from_shape(gc, srid=4612)

これでジオメトリオブジェクトが作成できたので、Plot インスタンスを生成して PostGIS に投入する。

plot = Plot()
plot.name = "test1"
plot.geom = geo

session.add(plot)
session.commit()

サンプルコードの完全版は以下の通り。

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, Integer, Text
from geoalchemy2 import Geometry
from geoalchemy2.shape import from_shape
from shapely.geometry.point import Point
from shapely.geometry.collection import GeometryCollection

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

db_url = "postgresql://gis:gis@localhost/gistest"
dat = [ [6,8], [8,1], [9,44] ]

db_engine = create_engine(db_url)
DBSession = sessionmaker(bind=db_engine)
session = DBSession()

class Plot(Base):
    __tablename__ = 'plots'
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    geom = Column(Geometry('geometry', 4612))

points = []
for i in dat:
  points.append(Point(i))

gc = GeometryCollection(points)
geo = from_shape(gc, srid=4612)

plot = Plot()
plot.name = "test1"
plot.geom = geo

session.add(plot)
session.commit()

これで、GeoAlchemy2 の使い方はだいたい解った。

]]>
Mon, 27 Jul 2015 00:00:00 +0900
http://blog.emaita.jp/2015/07/27/pyraid_gis3.html http://blog.emaita.jp/2015/07/27/pyraid_gis3.html <![CDATA[Pyraid + GeoAlchemy2 + GeoFormAlchemy2 (3)]]> Pyraid + GeoAlchemy2 + GeoFormAlchemy2 (3)

(承前)

Python コード内で GeoAlchemy2 を使う

サンプルとして下図のようなデータを作成した。

../../../_images/ga_sample.png

PostGIS 上で見ると、

gistest=> select * from plots;
 id |  name  |                                                                                                                                                               geom
----+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1 | points | 010700002004120000070000000101000000F2FFFFFF23932140DDFFFFFFF9364A400101000000E4FFFFFF47941E40DDFFFFFFF90C47400101000000E4FFFFFF47D81640DDFFFFFFF96647400101000000BAFFFFFF23C52B40DDFFFFFF797D47400101000000DDFFFFFF916B3B40DDFFFFFFB9B547400101000000DDFFFFFF91DC3340DDFFFFFF393449400101000000DDFFFFFF91553340DDFFFFFF79614540
(1 行)

一方、Pyramid 上でビュー函数を定義し、そこにデバッグ用 print 文を仕込んでみる。

@view_config(route_name='item', renderer='templates/plot.pt')
def item_view(request):
  item_id = request.matchdict['id']
  item = DBSession.query(Plot).filter(Plot.id == item_id).first()
  print item.geom

すると、pserve を実行したコンソール上に同じ文字列が出力される。

0107000000070000000101000000f2ffffff23932140ddfffffff9364a400101000000e4ffffff47941e40ddfffffff90c47400101000000e4ffffff47d81640ddfffffff96647400101000000baffffff23c52b40ddffffff797d47400101000000ddffffff916b3b40ddffffffb9b547400101000000ddffffff91dc3340ddffffff393449400101000000ddffffff91553340ddffffff79614540

これは OpenGIS の WKB (Well-Known Binary) フォーマットのデータを hex 表現したもので、PostGIS に格納されている元々のデータは バイナリである(と思われる)。 item.geom オブジェクトは geoalchemy2.elements.WKBElement クラスの インスタンスで、このクラスは data と desc の属性を持つ。 data 属性はバイナリ表現のデータを保持し、desc は data の内容を hex 化して 返す、@property でデコレーションされたメソッドである。

WKB を WKT (Well-Known Text) 形式に変換するには主にふたつの方法がある。 PostGIS サーバに変換させる方法と、ローカルマシンで処理する方法である。

PostGIS サーバに変換させるには、geom カラムに ST_AsText() 函数を適用すれば良い。 ビュー函数のデバッグ文を以下のように変更する。

print DBSession.scalar(item.geom.ST_AsText())

すると出力は、

GEOMETRYCOLLECTION(POINT(8.7873840332031 52.429504394531),POINT(7.6448059082031 46.101379394531),POINT(5.7112121582031 46.804504394531),POINT(13.885040283203 46.980285644531),POINT(27.420196533203 47.419738769531),POINT(19.861602783203 50.408020019531),POINT(19.334259033203 42.761535644531))

コレクションの中身を分割させるには ST_Dump() 函数を使う。

a = DBSession.execute(item.geom.ST_Dump().geom.ST_AsText())
for i in  a.fetchall():
  print i

出力は、

(u'POINT(8.7873840332031 52.429504394531)',)
(u'POINT(7.6448059082031 46.101379394531)',)
(u'POINT(5.7112121582031 46.804504394531)',)
(u'POINT(13.885040283203 46.980285644531)',)
(u'POINT(27.420196533203 47.419738769531)',)
(u'POINT(19.861602783203 50.408020019531)',)
(u'POINT(19.334259033203 42.761535644531)',)

各行がタプルになっている点に注意が必要だ。

ローカルマシンに変換させる場合は geoalchemy2.shape.to_shape() を使う。 ビュー函数を修正してアプリケーション再起動。

from geoalchemy2.shape import to_shape
@view_config(route_name='item', renderer='templates/plot.pt')
def item_view(request):
  item_id = request.matchdict['id']
  item = DBSession.query(Plot).filter(Plot.id == item_id).first()
  print to_shape(item.geom)

コンソール出力は以下のようになる。

GEOMETRYCOLLECTION (POINT (8.7873840332031 52.429504394531), POINT (7.6448059082031 46.101379394531), POINT (5.7112121582031 46.804504394531), POINT (13.885040283203 46.980285644531), POINT (27.420196533203 47.419738769531), POINT (19.861602783203 50.408020019531), POINT (19.334259033203 42.761535644531))

geoalchemy2.shape.to_shape() は shapely というパッケージを利用しており、 shapely は OS の libgeos を呼び出しているようだ。

to_shape() の返り値はオブジェクトで、この場合は <class ‘shapely.geometry.collection.GeometryCollection’> になる。このクラスはリストとして動作するのでスライス操作で要素を取り出すことが できる。 個々の要素は、この場合は <class ‘shapely.geometry.point.Point’> で、 POINT データの内容を更に操作することができる。たとえば X座標値だけを取り出すには

for i in shape.to_shape(item.geom):
    print i.x

などとすれば良い。

Python コードとの相性は geoalchemy2.shape の方が良さそうだ。 ただ、PostGIS と libgeos がトポロジー計算などでまったく同じ精度の 計算を行うのかどうかは確かめないといけない。

]]>
Mon, 27 Jul 2015 00:00:00 +0900
http://blog.emaita.jp/2015/07/24/pyramid_gis2.html http://blog.emaita.jp/2015/07/24/pyramid_gis2.html <![CDATA[Pyramid + GeoAlchemy2 + GeoFormAlchemy2 (2)]]> Pyramid + GeoAlchemy2 + GeoFormAlchemy2 (2)

(承前)

ジオメトリの種類を変える

models.py の point を multipoint に変えてみる。

class Plot(Base):
    __tablename__ = 'plots'
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    geom_point = Column(Geometry('multipoint', 4612))

テーブルを作り直してアプリケーション再起動。 すると下図のように、OpenLayers インターフェイス上で 多点指定ができるようになった。

../../../_images/multipoint.png

linestring と multilinestring、 polygon と multipolygon も同様の関係になる。

さて汎用の geometry を指定した場合にどうなるか、だが、

geom = Column(Geometry('geometry', 4612))

point, linestring, polygon を自由に指定できる。

../../../_images/geometry.png

geometry は geometrycollection でも良いようだ。

geom = Column(Geometry('geometrycollection', 4612))

複数カラム

ひとつのテーブルに複数のジオメトリカラムを作成した場合にどうなるか、 見てみる。models.py を以下のように修正してテーブルを作り直す。

class Plot(Base):
    __tablename__ = 'plots'
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    geom_geometry = Column(Geometry('geometry', 4612))
    geom_point = Column(Geometry('multipoint', 4612))
    geom_line = Column(Geometry('multilinestring', 4612))
    geom_polygon = Column(Geometry('multipolygon', 4612))

アプリケーションを再起動すると下図のようになる。 注意するべきは、2段目、3段目に表示されるべきデータが 4段目に表示されているところである。

../../../_images/multicolumn.png

これは、GeoFormAlchemy の renderer が、OpenLayers 用に、 まったく同一の JavaScript コードを 4回出力しているからだと思われる。 OpenLayers インスタンスへの参照を保持する変数名を使い回すことになるため、 4個目のインスタンスだけが変数に格納され、 1-3個目のインスタンスは、メモリ上には存在するが JavaScpript コードからはアクセスできないようになる。 結果的に、すべての入力内容が 4個目のインスタンスに渡されることになる、 ということなのだろう。 ただ、上図では 1個目のインスタンスだけは正常に動作しているようで、 それが何故なのか、この理屈ではよく解らない。

ちなみにこのまま save しようとするとエラーが出る。4個目のカラムは multipolygon 用であり、point や linestring を格納しようとするとエラーが 出るのである。

GeoFormAlchemy のこの挙動をバグと捉えるかどうかは悩ましいところである。 何故なら、OpenGIS では基本的に、ひとつのテーブルに対して ジオメトリカラムはひとつであることを措定しているからだ。 GIS は地物を扱う。地物には様々な属性が附属しており、ジオメトリも 属性のひとつである。ひとつの地物が複数のジオメトリを持つことはありえない。 何故なら地物はひとまとまりの物理的実体であり、従ってひとまとまりの ジオメトリしか持ち得ないからである。

よって、そもそも上記の models.py のような、ジオメトリタイプごとに カラムを分けるようなテーブル設計は OpenGIS の流儀から外れている、 ということだ。複雑なジオメトリデータを格納する場合は geometrycollection を 使うべきである。

なお、私は昨日まで PostGIS 等を使用したことがなく、OpenGIS に関する 上記の記述も、ついさっき小一時間調べただけに過ぎない。 私の理解が間違っているかも知れないので直ちに真に受けてはいけない。

(続く)

]]>
Fri, 24 Jul 2015 00:00:00 +0900
http://blog.emaita.jp/2015/07/24/pyramid_gis.html http://blog.emaita.jp/2015/07/24/pyramid_gis.html <![CDATA[Pyramid + GeoAlchemy2 + GeoFormAlchemy2]]> Pyramid + GeoAlchemy2 + GeoFormAlchemy2

SQLAlchemy を空間データに拡張した GeoAlchemy2 という パッケージがあるのを見つけた。 同様に FormAlchemy にも GeoFormAlchemy2 があるらしい。 早速試してみる。

PostGIS

PostgreSQL に PostGIS を導入。

FreeBSD pkg でインストールすると /usr/local/share/postgresql/extension に何もインストールされず、 create extention postgis が実行できない。 /usr/local/share/postgresql/contrib/postgis-2.1/ にある SQL ファイルを psql で投入するという従来の方法でデータベースをセットアップする。

$ cd /usr/local/share/postgresql/contrib/postgis-2.1/
$ su pgsql
# psql postgres
postgres=# create database gistest;
postgres=# create role gis with unencrypted password 'gis' login;
postgres=# \c gistest
gistest=# \i postgis.sql
gistest=# \i spatial_ref_sys.sql
gistest=# \i topology.sql
gistest=# \q

GeoAlchemy2

インストールは pip で。

$ pip install GeoAlchemy2

Pyramid 上で使用するには、たとえば models.py に以下のように 記述する。

from geoalchemy2 import Geometry
class Plot(Base):
    __tablename__ = 'plots'
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    geom_point = Column(Geometry('point', 4612))

細かい使用方法は後回しにして、先に GeoFormAlchemy2 をセットアップする。

GeoFormAlchemy2

pip でインストールする。

$ pip install GeoFormAlchemy2

現時点でインストールされるのはバージョン 2.0.dev3 であるが、 OpenLayers のURL が若干間違っているため、そのままだと上手く動作しない。 site-packages/geoformalchemy/pylons/project/+package+/templates/forms/map.mako を以下のように修正する。

) options['openlayers_lib'] = 'http://openlayers.org/dev/OpenLayers.js'
) options['openlayers_lib'] = 'http://openlayers.org/api/OpenLayers.js'

http://openlayers.org/api/OpenLayers.js はバージョン 2系で、 最新版の 3系ではない。 3系の URL を指定してみたが、上手く動作しないようだ。

さらに、pyramid_formalchemy 上で動かすためには、 forms.py に以下を追加する必要がある。

from formalchemy import FieldSet, Grid
from geoformalchemy import GeometryFieldRenderer
from geoalchemy2 import Geometry
FieldSet.default_renderers[Geometry] = GeometryFieldRenderer

動作テスト

この状態で Pyramid を起動し、 pyramid_formalchemy の admin UI で表示させてみる。

__init__.main() に pyramid_formalchemy の admin UI 設定が残っていることを確認。

config.include('pyramid_formalchemy')
config.formalchemy_admin('admin', package="alc")

テーブルを作成してアプリケーションを起動し、ブラウザで http://hogehoge/admin/Plot にアクセスすると以下のようになる。

../../../_images/point1.png

‘new plot’ ボタンを押すと、 OpenLayers のインターフェイスが現れ、 地図上で空間データが入力できる。今回は models.py で point を 指定したため、点がひとつしか指定できない(新しい点を指定すると 既存の指定点が消されてしまう)。point ではなく multipoint を 指定するとどうなるか、後で確認してみよう。

../../../_images/point2.png

‘save’ ボタンを押すとデータがテーブルに insert される。

../../../_images/point3.png

Geom 欄の背景に何も表示されていないように見えるのはズームのせいで、 ズームを調整すると背景にちゃんと地図があることが解る。

../../../_images/point4.png

(続く)

]]>
Fri, 24 Jul 2015 00:00:00 +0900
http://blog.emaita.jp/2015/07/22/pyramid2.html http://blog.emaita.jp/2015/07/22/pyramid2.html <![CDATA[Pyramid + SQLAlchemy + FormAlchemy (4)]]> Pyramid + SQLAlchemy + FormAlchemy (4)

(承前)

pyramid_formalchemy のビュー機能

pyramid_formalchemy には管理インターフェイスが附属しているので それを試してみる。

まず必要なパッケージをインストールする。

$ pip install webhelpers
$ pip install couchdbkit

alc/forms.py を作成する。 pyramid_formalchemy のマニュアル には空ファイルで良いとあるが、実際にはそんなことは無かった。 以下の行を記述する。

from formalchemy import FieldSet, Grid

__init__.main() に以下を追加する。

config.include('pyramid_formalchemy')
config.formalchemy_admin('admin', package="alc")

アプリケーションを再起動して http://hogehoge/alc/admin/ にアクセスすると 以下のように表示される。

../../../_images/admin_root.png

例えば Order をクリックすると Order クラスのレコードが表示される。 新規作成や編集もこの画面から可能である。

../../../_images/admin_order.png

構造が単純なデータベースを自分だけで使う場合は これで充分という気がする。

ユーザ認証

Pyramid 標準のユーザ認証システムは極めて単純で、 ビューごとにアクセス可能なユーザグループを指定する。 具体的には view_config デコレータに permission パラメータを与える。 データのレコードごとに permission を変えられるような丁寧な機能は 自分でコードを書かないといけないようだ。

Zope ではコンテンツオブジェクトごとにアクセス権限を設定できたり、 コンテンツオブジェクトのトラバーサル上の親子関係を追跡して アクセス権限を自動的に inherit するような機能があったが、 そういう機能は Pyramid 標準には無いのだろう。 まあ、Pyramid はフルスタックではないし、無い方が正しいように思う。

結論

手持ちのデータを RDB 化して、それの管理 UI が欲しいというだけなら pyramid_formalchemy の admin UI を基本に、多少の検索機能を自作する 程度で間に合いそうだ。

元々のプロダクトは Sphinx で作成しているため、 データを RDB 化した後、Sphinx からそれに接続してデータを抽出・整形するための 拡張を書かなければならない。 それとも、Sphinx には組み込まず、独立のスクリプトをプリプロセッサ的に 動かす方が良いか。

後で考えよう。

]]>
Wed, 22 Jul 2015 00:00:00 +0900
http://blog.emaita.jp/2015/07/22/pyramid.html http://blog.emaita.jp/2015/07/22/pyramid.html <![CDATA[Pyramid + SQLAlchemy + FormAlchemy (3)]]> Pyramid + SQLAlchemy + FormAlchemy (3)

(承前)

METAL

ZPT のマクロ機能である METAL を Pyramid 上で使用するのは簡単で、 ここ に書かれている通りである。要するに、マクロファイルを pyramid.renderers.get_renderer() でパースさせて、 そのインスタンスをテンプレートにデータとして引き渡せば良い。 マクロの記法自体は ZPT と同様である。 Zope では named template など、マクロオプジェクトへの特別な参照方法があったが、 pyramid-chameleon にはない、ことが違いか。

リレーション

テーブル間のリレーションの設定には 2種類が必要で、

  • RDBMS 上のテーブル定義での外部キー制約の設定
  • Python コード上でリレーションを扱うための設定

を別々に指定する。これらはモデルに指定する。

alc/models.py に以下を追加する。

class Order(Base):
  __tablename__ = 'orders'
  id = Column(Integer, primary_key=True)
  fruit_id = Column(Integer, ForeignKey('fruits.id'))
  amount = Column(Integer)

  fruit = relation(Fruit, backref=backref('orders', order_by=id))

ここで、fruit_id が RDBMS 上での外部キーを指示しており、 fruit がリレーション先の Fruit オブジェクトを格納する変数である。 Python コード上で fruit 変数にアクセスすると自動的にデータベースに クエリが発行されて対応する Fruit オブジェクトが fruit 変数に 格納されるという動作をする。

backref 云々というのはリレーション先の Fruit クラス上に 逆方向のリレーションを自動的に作成するように指示するコードで、 Fruit.orders に関連する Order オブジェクトが自動的に格納されるようになる。

モデルを追加したのでテーブルを作成する。

$ initialize_alc_db development.ini#truemain

Order 用に URL パターンを追加する。__init__.main() に

config.add_route('order', '/order')

そしてビューも追加する。views.py に

@view_config(route_name='order', renderer='templates/fruit.pt')
def order_view(request):
  num = DBSession.query(Order).count()
  action_url = request.route_url('order')

  if 'form.submitted' in request.params:
    up = FieldSet(Order, DBSession, data=request.POST)
    if up.validate():
      up.sync()
      DBSession.add(up.model)

  fs = FieldSet(Order, DBSession) # notice
  return {'number': num, 'form': fs.render(), 'action_url': action_url,
      'submit_label': 'Add New Order'}

ここで注意が必要なのは # notice の部分で、リレーションが無い場合は

fs = FieldSet(Order)

でも動作するのだが、リレーションを設定していると、リレーション先の テーブル内容を取得するために自動的にクエリが発行される場合があるため、 DBへのセッションを与えておく必要がある。上記の場合では return 文にある fs.render() を実行する時にリレーションを解決しようとするため、 セッションを指定しないと例外が出る。

Exception: No session found.  Either bind a session explicitly, or specify relation options manually so FormAlchemy doesn't try to autoload them.

さてアプリケーションを再起動して http://hogehoge/alc/order にアクセスすると TypeError が出る。

TypeError: lists/tuples are no longer allowed as elements in the 'options' arg: (u'', u'None')

これは WebHelpers2 の仕様変更に FormAlchemy が追従していないために 発生する例外である。PyPI 上にある最新の FormAlchemy は Ver 1.5.5 であるが、 GitHub には開発版の 1.6-dev があり、そちらのコードは WebHelpers2 の 仕様変更に追従している。変更点は 1行だけであるので、ローカルのファイルを 手作業で変更した方が早い。

修正が必要なファイルは formalchemy/helpers.py で、 diff は

@@ -173,7 +173,7 @@ def select(name, selected, select_options, **attrs):
     """
     if 'options' in attrs:
         del attrs['options']
-    select_options = _sanitize_select_options(select_options)
+    select_options = (tags.Option(*reversed(o)) for o in _sanitize_select_options(select_options))
     _update_fa(attrs, name)
     if six.PY3 and isinstance(selected,map): # this test fails with py2
         selected = tuple(selected)

アプリケーションを再起動して http://hogehoge/alc/order にアクセスすると このような画面が表示される。

../../../_images/order1.png

Fruit 欄にインスタンスのメタ情報が表示されてしまっているが、 これは Fruit クラスの __repr__() をオーバーライドしていないために デフォルトの __repr__() 函数が使用されているためである。 従って Fruit クラスの定義に __repr__() を追加する。

def __repr__(self):
  return self.name

アプリケーションを再起動するとドロップダウンメニューの表示が変わる。

../../../_images/order2.png

(続く)

]]>
Wed, 22 Jul 2015 00:00:00 +0900
http://blog.emaita.jp/2015/07/21/pyramid.html http://blog.emaita.jp/2015/07/21/pyramid.html <![CDATA[Pyramid + SQLAlchemy + FormAlchemy (2)]]> Pyramid + SQLAlchemy + FormAlchemy (2)

(承前)

次に、モデル作成からフォーム処理までの作業の概略を確認しよう。

モデル作成

Pyramid では全般的に、ファイル名やファイルパスに暗黙のルールは無いようだ。 だからモデル定義もどこに書こうが問題ないのだが、差し当たり、スケルトンの 初期ファイルを流用しよう。

alc/models.py に Fruit モデルを以下のように定義する。

class Fruit(Base):
    __tablename__ = 'fruits'
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    price = Column(Integer)

DB初期化スクリプト alc/scripts/initializedb.py に新モデルを記載する。

from ..models import (
    Fruit,
    )

スクリプトを実行すると PostgreSQL 上に fruits テーブルが作成される。

$ initialize_alc_db development.ini#truemain

URLディスパッチ

  • ‘/’ で新レコード追加ページを表示
  • ‘/{id}’ で ID が id のレコードの修正ページを表示

とする。

まず URL のパターンマッチを alc/__init__.py の main() に指定する。 ‘/’ 用は最初からスケルトンに含まれているのでそのまま残し、 ‘/{id}’ 用の指定を追加する。

config.add_route('home', '/')
config.add_route('item', '/{id}')

ここで、 home とか item とかいう文字列が URL パターンとビューを接続する キーワードとして働く。従ってアプリケーション全体でユニークでなければ ならない、はずだ。

‘{}’ はもちろんプレースフォルダとして機能する。

ビュー

ビューの登録には幾つかの方法があるらしいが、差し当たり、スケルトンをまねて view_config デコレータを使う。

たとえば以下のようなコードにしてみた。

from pyramid.view import view_config
from formalchemy import FieldSet

from .models import (
    DBSession,
    Fruit,
    )

@view_config(route_name='home', renderer='templates/fruit.pt')
def home_view(request):
  num = DBSession.query(Fruit).count()
  action_url = request.route_url('home')

  if 'form.submitted' in request.params:
    up = FieldSet(Fruit, DBSession, data=request.POST)
    if up.validate():
      up.sync()
      DBSession.add(up.model)

  fs = FieldSet(Fruit)
  return {'number': num, 'form': fs.render(), 'action_url': action_url,
      'submit_label': 'Add New Item'}

@view_config(route_name='item', renderer='templates/fruit.pt')
def item_view(request):
  item_id = request.matchdict['id']
  item = DBSession.query(Fruit).filter(Fruit.id == item_id).first()

  if 'form.submitted' in request.params:
    up = FieldSet(item, data=request.POST)
    if up.validate():
      up.sync()
      DBSession.add(up.model)

  action_url = request.route_url('item', id=item_id)
  fs = FieldSet(item)
  fs_ro = FieldSet(item)
  fs_ro.readonly = True
  return {'tgt': item, 'info': fs_ro.render(),
      'form': fs.render(), 'action_url': action_url,
      'submit_label': 'Update'}

要点としては、

  • ビュー函数の記述位置に制限はない(プロジェクトディレクトリの下であれば)。 __init__.main() の config.scan() が再帰的に探索するから。
  • ビュー函数は、テンプレートに渡すための辞書オブジェクトを返さねばならない。
  • URL ディスパッチのプレースフォルダは request.matchdict に格納される。

SQLAlchemy についてはここでは詳説しない。要するに、 SQL 文を Python 文法化 しただけのことだ。

さて問題は FormAlchemy の方だが、上記コードでは FieldSet を試している。 FieldSet にはセッションやフォームデータを渡すことができ、

  • モデルインスタンスの生成
  • フォームデータのバリデート
  • データベースの更新
  • フォームの HTML スニペットの生成

などの機能があり、便利そうではある。

ただし、すべてのデータ型に対応している訳ではなく、少なくとも ARRAY(TEXT) に対しては、

TypeError: No renderer found for field text_list. Type TEXT[] has no default renderer

というエラーが出て動作しない。 Zope では zope.formlib に sequencewidget というリスト型用のウィジェットが 最初からあって重宝したが、FormAlchemy ではそうはいかないようだ。 ORM では ARRAY など使わずに正規化する方が普通なのかも知れない。

テンプレート

Pyramid は Mako と Chameleon と2種類のテンプレートが使えるが、 このうち Chameleon は ZPT からの派生で、 TAL や METAL が使えるというので、 Chameleon を使う。

<!DOCTYPE html>
<html lang="${request.locale_name}">
  <head>
    <meta charset="utf-8">
    <title>Friut Database</title>
  </head>
  <body>
    <div tal:condition="number | nothing">
      Number of items: ${number}
    </div>
    <div tal:condition="tgt | nothing">
      ID: ${tgt.id}
      <table>
        ${info}
      </table>
    </div>
    <div>
      <form action="${action_url}" method="post">
        ${form}
        <input type="submit" name="form.submitted" value="${submit_label}"/>
      </form>
    </div>
  </body>
</html>

ZPT は ${} 構文が使えず、 tal:content や tal:attributes を使わなければ ならないところが煩雑だったが、 ${} が使えるだけで随分簡便になるものだ。

ブラウザ上の表示は、’home’ ビューが

../../../_images/home.png

‘item’ ビューが

../../../_images/item.png

のようになる。試験のため見栄えが良くないが、 METAL が使えるということはマクロが使えるということなので、 ページレイアウトをマクロ化したりすれば多少はマシなものが作れるだろう。

あと確認が必要なのは、

  • 外部キーを使ったリレーションに対する FormAlchemy の振る舞い
  • METAL
  • pyramid_formalchemy のビュー機能

あたりか。

(続く)

]]>
Tue, 21 Jul 2015 00:00:00 +0900
http://blog.emaita.jp/2015/07/17/pyramid.html http://blog.emaita.jp/2015/07/17/pyramid.html <![CDATA[Pyramid + SQLAlchemy + FormAlchemy]]> Pyramid + SQLAlchemy + FormAlchemy

PostgreSQL 上のデータベースに対する UI が欲しいと思い、 表題のような組み合わせを検討したので記録しておく。

PostgreSQL 上で create database, create role, grant の作業は 済んでいるという前提。

インストール。

$ pip install pyramid
$ pip install sqlalchemy
$ pip install pyramid-sqlalchemy
$ pip install psycopg2
$ pip install FormAlchemy
$ pip install pyramid_formalchemy
$ pip install pyramid-chameleon

プロジェクト作成。

$ pcreate -s alchemy alc
$ cd alc
$ python setup.py develop

設定ファイル development.ini 修正。

[app:truemain]  <- [app:main] から変更
..snip..
sqlalchemy.url = postgresql://alc_admin:alc_pass@localhost/alc

[composite:main]    <- URL調整のために追加
use = egg:Paste#urlmap
/alc = truemain

初期化と起動。

$ initialize_alc_db development.ini#truemain
    (#section を指定しないと [composite:main] に sqlalchemy.url が
        あるものだと仮定して処理するようで、エラーが出てしまう。)

$ pserve development.ini

ブラウザで http://hogehoge/alc/ にアクセスすると Pyramid のトップページが表示されるはず。

(続く)

]]>
Fri, 17 Jul 2015 00:00:00 +0900
http://blog.emaita.jp/2015/07/07/ciniiarticle.html http://blog.emaita.jp/2015/07/07/ciniiarticle.html <![CDATA[CiNii Articles に書誌情報を載せるには]]> CiNii Articles に書誌情報を載せるには

きっかけは単なる思いつきで、職場で発行しているニュースレターの記事を CiNii Articles で検索可能にできたらいいな、と。

CiNii Articles での学術出版物の判別基準がどうなっているのか知らないが、 ニュースレターは学術出版物と認められるらしい。たとえば 日本地球惑星科学連合 JpGU のニュースレター JGL は記事の書誌情報が CiNii Articles に 収録されており、たとえば http://ci.nii.ac.jp/naid/40020474066 のようである。 右隅に表示されているように、情報の出所は国会図書館(NDL)らしい。 つまり JpGU は JGL の冊子体を NDL に納本しており、NDL は JGL を雑誌記事索引の 収録対象にしている、ということだ。実際に NDL の採録誌一覧に JGL が 載っている ( ここ )。

CiNii Articles は基本的に既存のデータベースを統合しているだけで、 自力でゼロから収集している訳ではない。そこで、CiNii Articles に書誌情報を 載せるにはその情報源となっているデータベースに情報を流すことになる。

最初に検討したのは JaLC で、その理由は、そもそもこれらのことを考え始めたのは JaLC の 「研究データへのDOI登録実験プロジェクト」 に参加するようになって、どうせならついでに出版物にも DOI を振ったらいいじゃん、と 考えたからだ。JaLC に DOI を登録する際には JaLC メタデータと呼ばれる情報を 提出するので、その情報をそのまま JaLC から CiNii に流して貰えれば楽ちんだな、 と思ったのである。

しかしこの案は駄目だと判った。JaLC は2,3 年前から論文情報の DOI 登録を扱っているが、 CiNii Articles には JaLC のデータベースは収録されていない。それには理由があって、 JaLC の会員はほとんどが NII の JAIRO か JST の J-Stage を利用している 大学または学協会で、JAIRO と J-Stage は元から CiNii Articles の情報源になっているため、 JaLC からメタデータを CiNii に流すことは基本的に二度手間にしかならないのである。

次に考えたのは、CiNii Articles が CrossRef を情報源にしていることから、 JaLC 経由で CrossRef に DOI 登録し、CrossRef 経由で書誌情報を CiNii Articles に 流す、という方法である。この方法の欠点は、CiNii Articles に収録させるためだけに CrossRef を利用することの妥当性に疑問があること(CrossRef に登録すると JaLC 会費とは別に 費用がかかる)で、現実的な選択肢ではないと思われる。

他に良い方法が無いかと考えてみたところ、NII の 学術機関リポジトリデータベース IRDB 経由で流す方法があることに気付いた。IRDB は国内の学術機関リポジトリに格納されている 書誌情報等を収集して蓄積しているデータベースで、 CiNii Articles の情報源のひとつに なっている。IRDB は基本的には大学や大学共同利用機関を対象にしているようだが、 運用規程 によると、特に大学に限定している訳ではないようだ。つまり国環研も、 条件を満たせば IRDB に書誌情報等を格納してもらえる筈である。

その条件は、提供リポジトリのシステムが、

  • OAI-PMH を喋れる
  • junii2 形式のメタデータを吐ける

ことである( 詳細 )。 このうち OAI-PMH は世界的な標準プロトコルなのでいいとして、 NII 独自の junii2 フォーマットに対応できるかどうかが要点となる。

ところで junii2 には DOI 用の項目が 2種類あり(selfDOI, doi)、用途が異なる。 selfDOI は、情報提供機関が NII 傘下の JaLC 準会員となり、NII 経由で JaLC に DOI を登録する際に利用する項目で、一方の doi は NII とは無関係に情報提供機関が独自に DOI を取得した場合に利用する項目である。両方の選択肢が用意されている点は 評価して良いだろう。

さて junii2 への対応であるが、技術的には OAI-PMH + junii2 など大して高度なものではないが、 自分でリポジトリシステムを作るとなると大変面倒くさい。 出来合いのソフトウェアとして NII のウェブサイト には DSpace や WEKO が挙げられている。 DSpace は広く使われているリポジトリシステムで、CGER でも7,8年前に導入が 検討されたことがある。junii2 用のプラグインを導入すれば junii2 が吐けるようになる ようなことがウェブページに書いてあるが、詳しいことは判らない。 WEKO は NII が自ら作成したソフトで、NetCommons のモジュールとして動作し、 JAIRO クラウドの基盤として使用されている。 他に理研制作の XooNIps が挙げられているが、フレームワークが Xoops Cube で、 今から導入するシステムに Xoops Cube を使うのはどうなのかという気がするので 個人的には避けたい。

機能やデザインに拘らないのであれば、WEKO を使うのが一番手っ取り早い。 という結論を得て、ちょっと WEKO を試用してみようとしたのだが、 公式サイト にまともなドキュメントが無く、一通り動かすのに苦労した。 試行錯誤したため必要十分な手順が判らなくなってしまったので、 後で再検証するか。時間があれば。

]]>
Tue, 07 Jul 2015 00:00:00 +0900
http://blog.emaita.jp/2015/07/01/ndlsearch.html http://blog.emaita.jp/2015/07/01/ndlsearch.html <![CDATA[国立国会図書館サーチから書誌情報を抜く]]> 国立国会図書館サーチから書誌情報を抜く

CiNii に続いて NDL から書誌情報を取得する方法を検討する。 以下、調査結果を記す。

最初に注意しなければならないのは、API を提供しているのは 国立国会図書館サーチ(NDLサーチ)であり、NDL-OPAC ではない、 ということだ。なぜこれが重要かと言うと、両者は検索する データベースの範囲が異なり、そのため ID の体系が異なるからである。

ID

NDL-OPAC の書誌ID は、たとえば 000001887364 のような形式になっており、 http://id.ndl.go.jp/bib/000001887364 というURLで書誌ページにアクセスできる。 一方、NDLサーチの方では ID は R100000002-I000001887364-00 という形式で、 書誌ページの URL は http://iss.ndl.go.jp/books/R100000002-I000001887364-00 となる。ここで R100000002 というのは NDL-OPAC を表すリポジトリ番号で、 つまり R100000002-I000001887364-00 という ID は、 NDL-OPAC 内の 000001887364 番のレコードを指している。 末尾の 00 の意味は不詳であるが、おそらく分冊になっていたり別冊が あったりする場合に使用するのではなかろうか。

雑誌記事の場合、NDL-OPAC の記事登録IDは 026093161 のような形式になっており、 http://id.ndl.go.jp/bib/026093161 というURLで書誌ページにアクセスできる。 NDL-OPAC では図書用の書誌ID と記事用の記事登録IDは区別する必要はなく、 ユーザインターフェイス上ではシームレスに扱われている。 一方、NDLサーチの方では、雑誌記事は別リポジトリになっており、 R000000004 というリポジトリ番号が割り当てられている。 従って ID は R000000004-I026093161-00 となり、書誌ページのURLは http://iss.ndl.go.jp/books/R000000004-I026093161-00 となる。NDL-OPAC の ID を NDLサーチに流用する場合は、 図書か記事かをユーザの側が意識してリポジトリ番号を選ぶ必要がある。

書誌データの取得

NDLサーチのサイトに 外部提供インタフェース(API) というページがあって、ここに OAI-PMH 云々と書かれているので、 OAI-PMH を使わなければ書誌データが取れないのかと思ったが、 別にそんなことはなく、書誌ページの URL の末尾に .rdf または .json を 付加すれば良い。RDF形式の方は OAI-PMH API でメタデータ形式として dcndl を指定した時と同じ内容になるようだ。JSON 形式は内容をかなり 簡素化して返す。

実用上は JSON 形式の簡素化データで問題ないが、ひとつだけ懸念すべき点があった。 それは図書と記事の判別である。図書と記事では書誌の項目が異なっていたので 区別する必要がある。RDF形式では

<dcndl:materialType rdf:resource="http://ndl.go.jp/ndltype/Book" rdfs:label= "図書"/>

のように、URI形式の識別子があるのでまったく問題がないが、JSON形式では URI形式の識別子がなく、日本語リテラル(上記の rdfs:label の内容)だけが 与えられるようになっている。日本語リテラルで判別するとすると、 エンコードや「・」(中点)の揺れが原因で文字列比較が失敗する可能性が 考えられ、出来るなら避けたいところである。そこで RDF形式で取得して こちらでパースすることを検討したが、それはやはり面倒くさいという 結論になった。NDL側で語彙統制している筈だから表記揺れは無いだろう、と 措定することにした。

ライブラリっぽいものが落ちてないかと探してみたが無さそうだ (まぁそうだろう)。自分で書かなければならないか。

]]>
Wed, 01 Jul 2015 00:00:00 +0900
http://blog.emaita.jp/2015/06/30/ciniiwebapi2.html http://blog.emaita.jp/2015/06/30/ciniiwebapi2.html <![CDATA[CiNii Web API 2]]> CiNii Web API 2

(承前)

実用上の問題としては、ライブラリがないことが一番の障害だ。 CiNii の公式サイトに見当たらないし、利用者の「試してみた」記事にも無い。 まぁちょっと試してみる程度の動機ではそれなりのコードを書く気にも ならんだろう。しかし NII は過去にアプリコンテストなどを開催しているが、 そんなコンテストするよりは主要言語用のライブラリを整備した方が よっぽど利用者が増えると思うのだが、本末を間違えてるんじゃないのかそれ。

まぁいい。

さて python で書くとすると requests が便利だが、requests.Response に json() という JSON パーサがあるようなので、これを使うことにした。 つまり、書誌情報を CiNii Web API から JSON-LD 形式で取得し、これを requests の JSON パーサで python オブジェクト化してから取り出す。

JSON データを解析したりしながら約 2日、出来たのが これ 。元々の JSON-LD 形式というのが 妙に煩雑なせいか、不格好なコードになってしまった。

ciniiwebapi.py の使い方

Python 2.7用。その他のバージョンではテストしていない。

  1. CiNii からデベロッパーID を取得しておく。
  2. requests をインストールしておく。
  3. ciniiwebapi.py を適当な場所に置く。

以下、テストコード。NAID 110009810897 の論文のタイトルを取り出す。

>>> import ciniiwebapi
>>> cwapi = ciniiwebapi.CWAPI("your developer_id")
>>> cite = cwapi.query("110009810897")
>>> cite.title
「研究データ公開」における人材と体制の問題 : 研究図書館の可能性(学術情報)

dir() を取れば抽出可能な項目が判る。

>>> dir(cite)
['authors', 'authors_en', 'authors_num', 'pages', 'publication', 'publication_en', 'publisher', 'publisher_en', 'title', 'title_en', 'volume', 'year']

項目によっては list になっていたり unicode になっていたりするので、 そこは適当に処理する。

>>> for i in dir(cite):
...  data = getattr(cite, i)
...  if isinstance(data, list):
...    data = u", ".join(data)
...  if isinstance(data, unicode):
...    data = data.encode("utf-8")
...  print "{}: {}".format(i, data)
...
authors: 真板 英一
authors_en: Maita Eiichi
authors_num: 1
pages: 81-86
publication: 日本生態学会誌
publication_en: Japanese Journal of Ecology
publisher: 日本生態学会
publisher_en: The Ecological Society of Japan
title: 「研究データ公開」における人材と体制の問題 : 研究図書館の可能性(学術情報)
title_en: Professions and facilities for the research data publication : the potential of research libraries(News)
volume: 64
year: 2014

この程度のものでも作るのにそれなりの時間がかかる。 それが節約できるかどうかは開発者にとっては無視できないと 思うのだが、そう思う人は少ないのだろうか。

]]>
Tue, 30 Jun 2015 00:00:00 +0900
http://blog.emaita.jp/2015/06/30/ciniiwebapi.html http://blog.emaita.jp/2015/06/30/ciniiwebapi.html <![CDATA[CiNii Web API]]> CiNii Web API

PlotNet のサイトを作っていて、文献情報をいちいちコピペするのが 面倒なので、外部DBから取って来れないものかと思い、まずは CiNii の API サービスを調べてみた。

まず “CiNii API” 等でググってみると、検索上位には CiNii の公式サイトが並び、 その他は「試しにちょっと使ってみた」程度のページが数える程度出てくるだけで、 世間ではあまり流行っていない、という印象を持った。 この API サービスが始まったのは 2009年頃のようで、その当時は NII が API を使用したアプリ開発のコンテスト を開催したようだが、2009, 2010年に 1回ずつ開催しただけで終わったようだ。 一方で API の開発は継続されており、 2013年に JSON-LD 形式に対応するなど 機能拡張が進められている。内部事情はよく知らないが、限られた人員・予算で 細々と継続しているのであろう。

さて、この API を利用するにはデベロッパー登録というものを しなければならないことになっている。実際には無登録でも、 少なくとも書誌情報を RDF または JSON-LD 形式で取り出すことは可能で、 たとえば http://ci.nii.ac.jp/naid/110009810897.rdf などと URL の末尾に .rdf 等を付加すれば良い。おそらくこの登録というものは CiNii の側で API の利用状況を把握するために利用するのであろう。 有料という訳でもないし、素直に登録することとした。

ところで、 API 登録者は API 利用に関して 学術コンテンツサービス利用規程 なるものを遵守せよ、と要求されるのであるが、この規程というのが なかなか曲者である。たとえば第4条に、

(利用目的)
第4条 何人も自己の学術研究に利用するため,本サービスを利用するものとし,それ以
外の目的のために使用しないことに同意する。

とあるが、API を使用するアプリを作って第三者に提供した場合、 (自己ではなく)その第三者の学術研究のために API を利用したことになってしまうため、 通常の意味でのアプリ開発は不可能ということになってしまう。 アプリを開発者自身しか使わない場合は問題ないが、先述の通り、 NII 自体が過去にアプリコンテストなるものを開催して第三者使用を奨励しており、 明らかに矛盾している。

他には第5条2項の一、

一 複製,改変,翻訳及び編集等を行ってはならない。ただし,自己の学術研究に利用
するためダウンロードし又は印刷することができる。

アプリというものは適宜、 API で得た情報を編集加工してアプリ利用者に提示するものであって、 編集するべからずという要求は理解に苦しむ。

つまりこの条文は公開 API の提供を想定していない ものであって、API 登録者に遵守を求めることが無理なのである。 この点を CiNii の担当者は認識しているのだろうか。 この規程を修正するか、または API利用者用に別に規程を策定するか、 どちらかの対応が必要と思われる。 CiNii Web API が世間で利用されている形跡が少ないのは この規程の不備も原因のひとつなのだろうか。

まあ良い。規程の問題は当面無視する。

]]>
Tue, 30 Jun 2015 00:00:00 +0900
http://blog.emaita.jp/2015/06/17/vim_indent.html http://blog.emaita.jp/2015/06/17/vim_indent.html <![CDATA[Vim のインデント幅]]> Vim のインデント幅

Python では公式にはインデント幅は 4 にすることになっているようだが、 個人的には 4文字幅は深過ぎると思っている。 真面目な(書き捨てでない)コードの場合、主要な部分はだいたいインデントの 3-4段目に来ることになる。つまり、

class CLASS:
  def __init__(self):
    if a:
      hogehoge(3段目)
      for i in b:
        hogehoge(4段目)

さてそうすると、4文字幅の場合、4段目のインデントでは無条件に 16文字分の領域が消費されてしまうことになる。 一行の文字数が約70文字しか無いのに、その 2割強があらかじめ使えないとなると、 コード記述の自由度が低く、窮屈である。 私はこの窮屈さが嫌いで、インデント幅を 2文字に減らして python コードを 書いてきた。別に書いたコードを PyPI に登録したりする訳でもないので、 個人の勝手の範囲である。

さて、さっき、 FreeBSD 上の vim で python コードを書こうとしたら、 自動インデントの幅がいつの間にか 4 になってしまっていて戸惑った。 色々調べてみたところ、先日、サーバ上で何かをアップデートした時に pkg の vim にアップグレードが掛かってしまい、 filetype 関係の 定義ファイルが書き変わってしまったようだ、と考えられた。 /usr/local/share/vim/vim74/ftplugin/python.vim に

" As suggested by PEP8.
setlocal expandtab shiftwidth=4 softtabstop=4 tabstop=8

という行があり、おそらくこれがアップグレード時に追加されたのだろう。

この設定は ~/.vimrc の指定を上書きするらしく、~/.vimrc の中での 記述順を変えたりしても無駄であった。

ググってみたところ、~/.vim/indent/ にインデントに関する個人設定が 置けるようだったので、試しに ~/.vim/indent/python.vim に

setlocal shiftwidth=2

と指定したら、以前の通り、自動インデントが 2文字に戻ったのであった。

]]>
Wed, 17 Jun 2015 00:00:00 +0900
http://blog.emaita.jp/2015/06/15/dump_without_postgis.html http://blog.emaita.jp/2015/06/15/dump_without_postgis.html <![CDATA[pg_dump で PostGIS を無視するには]]> pg_dump で PostGIS を無視するには

PostgreSQL のバージョンアップを他人任せにしたら、 PostGIS 用のテンプレート上にリストアされてしまって、 pg_dump に余計なものが混じるようになってしまった。

取り敢えず、PostGIS 用のビューとテーブルを削除したものの、 他にデータタイプと函数が大量に登録されていて、気が遠くなる。 幸いなことに、今まではデータタイプも函数も使用していなかったので、 これらをまとめて全部無視すれば良いということが判った。

調べてみると、pg_dump には –table オプションがあり、これは テーブル、ビュー、シーケンスのみをダンプする機能であった。 試しに使ってみると、テーブル作成からインデクス、外部キー制約まで 一通り出力してくれるようだ。

他に –data-only というオプションもあるが、こちらは 外部キー制約が上手く出力できないようで、 notice が出力された。 これは使わない方が良いだろう。

結論としては以下のようになる。PostGIS は topology という スキーマを作成するので public.* と指定した方が間違いがない。

# pg_dump -h host -U user -c --table="public.*" database

なお、PostgreSQL のスキーマには 2重の意味があって、最初は混乱した。 実際に pg_dump の man にもそう書いてある。:

--schema-only
     .. snip ..
    (Do not confuse this with the --schema option, which uses the word
    "schema" in a different meaning.)

–schema の方は名前空間の方の意味で、 –schema-only の方は テーブル定義の方の意味である。

生半可だった知識を整理する機会にはなった。

]]>
Mon, 15 Jun 2015 00:00:00 +0900
http://blog.emaita.jp/2015/05/27/nastools.html http://blog.emaita.jp/2015/05/27/nastools.html <![CDATA[NAStools, NASA Ames フォーマット用ツール]]> NAStools, NASA Ames フォーマット用ツール

NASA Ames Format for Data Exchange というデータ形式があって、 地球科学関係の分野でよく使われている。

このフォーマットを扱える Python パッケージはないものかと PyPI を 探したところ、 2つ見つかった。

nappy:NASA Ames を NetCDF に変換したりする機能があるようで、 インストールに NetCDF のライブラリが必要で面倒なので 後回し。
NAStools:FFI 1001 しか対応していないようだが、職場には 1001 の データしか無いようなので問題なし。

という訳でまず NAStools から試す。

NAStools 試用

virtualenv 関係は省略。

依存パッケージ含めてインストール。

$ pip install numpy
$ pip install pandas
$ pip install NAStools

クイックガイド を参考に使ってみる。サンプルデータは ここ から拾った。

$ curl -O http://badc.nerc.ac.uk/help/formats/NASA-Ames/example-1001-a.na
$ python
>>> import nastools
>>> ex = nastools.Naspy("example-1001-a.na")
>>> ex
NAS Data File (FFI = 1001)
example-1001-a.na

データファイルのヘッダの内容は Naspy.header に格納される。

>>> dir(ex.header)
['COLUMN_VARIABLES', 'DATA_DESCRIPTION', 'DATA_INTERVAL',
'DEPENDENT_VARIABLE', 'FFI', 'FILENAME', 'FILE_VOL_NO', 'HEADER_LINES',
'INDEPENDENT_VARIABLE', 'MISSING_DATA_FLAGS', 'MISSION', 'NORMAL_COMMENTS',
'NORMAL_COMMENT_LINES', 'NO_VOL', 'ORGANIZATION', 'PI', 'REV_UTC',
'SCALE_FACTORS', 'SPECIAL_COMMENTS', 'SPECIAL_COMMENT_LINES', 'START_UTC',
'TOTAL_NUM_VARIABLES', '__class__', '__delattr__', '__dict__', '__doc__',
'__format__', '__getattribute__', '__hash__', '__init__', '__module__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'_fileAbsPath_', '_fileObj_', 'contact_info', 'data_description',
'parse_header']

各属性の内容は属性名を見れば判るだろう。

クイックガイドには Naspy.header.INSTRUMENT_INFO という属性がある ことになっているが、最新版では Naspy.header.DATA_DESCRIPTION に 変わったようだ。

>>> ex.header.DATA_DESCRIPTION
'Meteorological sensors'

Naspy.header.COLUMN_VARIABLES は、 normal comment の最終行が、データのカラム数と同じ個数に split できると その内容が格納される、という仕様のようだ。 なお、ファイルを編集してコメント最終行の構造を壊すと、header オブジェクトに この属性自体がセットされなかった。

>>> print ex.header.COLUMN_VARIABLES
['t', 'T', 'p', 'RH']

似たような機能に Naspy.get_column_names() があるが、こちらは アルファベットを勝手に大文字化してしまう。

>>> print ex.get_column_names()
['T', 'T', 'P', 'RH']

クイックガイドには Naspy.time に関する記述があるが、 Naspy.time.start_time() も Naspy.time.end_time() も動作しなかった。

データ部分は numpy で扱える。

>>> ex.make_numpy()
array([(38927.0, 10.0, 99.0, 0.6), (38927.020833, 10.1, 98.9, 0.591),
       (38927.041667, 9.5, 99.3, 0.62), (38927.0625, 9.2, 99.5, 0.632),
       (38927.083333, 9.3, 99.4, 9.999), (38927.104167, 8.9, 99.9, 9.999),
       (38927.125, 8.5, 100.1, 0.632), (38927.145833, 8.9, 99.8, 0.622),
       (38927.166667, 9.4, 99.7, 0.61), (38927.1875, 10.1, 99.5, 0.604),
       (38927.208333, 10.2, 99.3, 0.595), (38927.229167, 10.4, 99.0, 0.58),
       (38927.245, 10.3, 99.2, 0.587)],
      dtype=[('T', '<f8'), ('T_1', '<f8'), ('P', '<f8'), ('RH', '<f8')])

依存パッケージの pandas は時系列解析のパッケージらしいので、 もしかしたら簡単な解析もできるのかも知れない。 後で調べてみよう。

]]>
Wed, 27 May 2015 00:00:00 +0900
http://blog.emaita.jp/2015/05/01/morpho1_11.html http://blog.emaita.jp/2015/05/01/morpho1_11.html <![CDATA[Morpho 1.11.0 リリース]]> Morpho 1.11.0 リリース

EML エディタ Morpho の新バージョン 1.11.0 がリリースされたとのこと。 インストーラ付きバイナリは KNB からダウンロードできる。

リリースノートによると、新バージョンでは Java 6 のサポートを打ち切った模様。 手元の Macbook OS X 10.9 では Java 8、FreeBSD 10.1R では Java 7 が デフォルトになっているようなので、まったく実害はない (Windows は知らないし、興味もない)。 と言うか、リリースノートにはそれしか書いてないのだが、他に変更点はないのだろうか。 新機能の追加などはせず、古いコードを削ることに注力したのかしら。 Java なんぞ普段書かないから事情が解らん。

実は Morpho 1.10 系列をちゃんとフォローしていなかったので Morpho の change log を読むのは久しぶりなのだが、読んでみると 面白いことが書いてある。 ひとつはメタデータを PDF で出力できる機能で、「ファイル -> エクスポート」で 出力してみると、確かに PDF が現れる。

../../../_images/exportaspdf.png

中身はこんな感じ。

../../../_images/metadata.png

正直、見易いんだか見難いんだかよく判らない。

もうひとつは、キーワードの入力に IMS VDEX という技術を導入して、 出来合いのシソーラスから定義済みのキーワードを選択できるようになったこと。 入力画面はこんな感じ。

../../../_images/keyword.png

IMS VDEX (Vocabulary Definition Exchange) というのは学習支援やナレッジベース関係の用途で作られた仕様で、 ボキャブラリ情報をやり取りするためのもの、らしい。 ググってもあまり情報が出てこないので、流行らなかったのかも知れない。 日本語だと IBM の技術情報のページ が出てきた。正確な経緯はともかく、大体の文脈はこれで解る。

調べると PyPI にも、 VDEX で書かれたボキャブラリ情報を Zope vocabulary オブジェクトに変換するパッケージが登録されている。そのパッケージの 説明には、ツリー構造のボキャブラリを自動処理できるところが売りだ、と 書かれているが、確かにそのような複雑な構造の情報だとこういうツールが欲しくなる かもな。

新バージョンをインストールしてみたが、EML エディタの機能としては ほとんど進化はないようだ。

]]>
Fri, 01 May 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/23/unicodedata.html http://blog.emaita.jp/2015/04/23/unicodedata.html <![CDATA[ユニコード文字列の「長さ」]]> ユニコード文字列の「長さ」

文書作成ツールの利便性のひとつは参照関係を自動解決してくれるところにあり、 sphinx だと :ref: などがそれに当たる。

この機能を表の中でも使いたいと思い、 csv-table で :ref: を含んだデータを 読み込ませたのだが、sphinx が :ref: を解釈してくれず、そのまま出力されてしまった。 この時、実は、:ref: の記述をミスしていて、そのために参照が解決されなかったのだが、 普段 csv-table をあまり使わないせいで、「csv-table だと :ref: を解釈してくれない」と 思い込んでしまい、csv を grid table に整形するスクリプトを自作しようと 思ったのが発端である。

大きな csv(精確にはssv)データを手作業で grid table 化するのは面倒なので、 自動変換スクリプトを書こうと思うのは当然だが、書き始めてすぐに、 文字列長に関して疑問が生じた。grid table は罫線を精確に揃えて記述しなければ ならない形式であり、文字列長を厳密に計算する必要があるが、 マルチバイト文字列が含まれている場合に 文字列長をどのように計算しているのか、ということだ。

私は普段 ターミナル + Vim で作業しており、grid table を書く場合には 画面の見た目通りに書く。すなわち、Ascii文字は 1文字分、全角文字は 2文字分として 計算すれば sphinx のビルドが通る。しかしこれは不思議なことで、 UTF-8 だと日本語文字は 3バイト以上になるし、unicode オブジェクトに len() を 取ると1文字扱いだし、UTF-16 にすると逆に Ascii 文字が 2バイトに計算され、 全角/半角概念とは綺麗には整合しない。

不思議に思って sphinx のコードを追ってみたら、 docutils の方で、 unicodedata.east_asian_width() を呼んでいることが判った (docutils/statemachine.py)。 これは Unicode Standard Annex #11 に基づくもので、文字の表示幅を返す函数らしい。 docutils ではこれを利用して、画面上の見た目に合うように内部データを 修正している。

こんな便利な函数があるとは知らなかった。と言うか unicodedata ライブラリ自体 知らなかった。”unicodedata.east_asian_width” でググっても 1500件くらいしか ヒットしないので、世間でもあまり知られていないのかも知れない。

なお、:ref: の記述ミスに気付いたのはスクリプトが完成してからで、 完全な時間の無駄だった。馬鹿馬鹿しいが、勉強にはなった。

]]>
Thu, 23 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/20/gsimap.html http://blog.emaita.jp/2015/04/20/gsimap.html <![CDATA[地理院地図拡張を geojson 化]]> 地理院地図拡張を geojson 化

何気なく地理院地図のサイトを開いてツールをいじっていた時、 作図ツールの中に円があることに初めて気付いた。これ、前から あったっけか。それとも最近追加されたのか。

大雑把に範囲指示したい時にポリゴンよりも楽ちんかなと思い、 ちょっと作図してみたが、保存する時、KML と geojson でコードが違った。 KML だとポリゴン扱いで、円弧上の30個くらいの点を繋いで疑似円を 描画するようなコードだったのに対し、 geojson だと CircleMarker という 円図形の扱いで、中心座標と半径から円を描画するようなコードが出た。

これを見て、短絡的に、geojson には円が定義されているのかと思ったが、 調べてみるとそうではなく、geojson の規格にはKMLと同様に点・線・ポリゴンしか 定義されていない。じゃあ CircleMarker というのは何かと言うと、 Leaflet という JavaScript ライブラリで定義されているマーカだった。

以前調べた時には、地理院地図ではKMLかgeojsonでレイヤを記述できるが、 geojsonの方はまだ仕様が詰められていなくて、変更の可能性がある、という ことだったので、自作 Sphinx 拡張では KML を生成するようにしたのだった。 でも円が使えると便利だなーと思い、geojson を出力するように書き直した。

geojson形式だと、アイコンにアンカー点を指定できるので、Google Map で よく見られるピン/バルーン型のマーカアイコンも精確な位置に表示できる。 これも書き直す動機のひとつではあったが、改めて表示させたいデータを見ると、 特定の地域では点が密集していて、バルーン型のアイコンは明らかに邪魔すぎる と思い、従来の小ボタン型アイコンを使い続けることにした。

細かな点では、KML形式では色指定がなぜか #bbggrr というフォーマットで あったが、geojson では普通に #rrggbb で、混乱が少なくて良い。 あと半径の指定は、Leaflet のドキュメントにはピクセル単位と書かれているが、 地理院地図ではメートル単位のようだ。単位変換してから Leaflet に流している んだろう。

]]>
Mon, 20 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/17/pyramid_test.html http://blog.emaita.jp/2015/04/17/pyramid_test.html <![CDATA[Pyramid のテスト]]> Pyramid のテスト

物は試しで起動するところまで。

virtualenv でテスト環境を作るところは省略。

Pyramid 本体のインストール

(pyramid)$ pip install pyramid

新規プロジェクト作成

pcreate コマンドでプロジェクトの初期ファイル群を生成できる。 以下の 3種類の型が選ぶことができるが、

(pyramid)$ pcreate -l
Available scaffolds:
  alchemy:  Pyramid SQLAlchemy project using url dispatch
  starter:  Pyramid starter project
  zodb:     Pyramid ZODB project using traversal

もちろん zodb を選ぶ。

(pyramid)$ pcreate -s zodb testproj

プロジェクトの実行環境を整える。

(pyramid)$ cd testproj/
(pyramid)$ python setup.py develop

Http アクセスの設定

トップベージの URL を http://pyramid.myserver.jp/testproj/ とする。

Apache httpd の設定に以下を追加して reload する。

<VirtualHost *:80>
  ServerName pyramid.myserver.jp

  ProxyPreserveHost On
  ProxyPass /testproj http://localhost:6543/testproj
  ProxyPassReverse /testproj http://localhost:6543/testproj
</virtualHost>

testproj/development.ini の設定を変更。

[composite:main]      <- 追加
use = egg:Paste#urlmap
/testproj = truemain

[app:truemain]        <- [app:main] から変更

何故か Paste がインストールされていないので入れる。

(pyramid)$ pip install Paste

起動

(pyramid)$ pserve development.ini

ブラウザで http://pyramid.myserver.jp/testproj/ にアクセスして 以下の画面が表示されたら正常。

../../../_images/pyramid_top.png
]]>
Fri, 17 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/17/python_framework.html http://blog.emaita.jp/2015/04/17/python_framework.html <![CDATA[Python ウェブフレームワークの現況]]> Python ウェブフレームワークの現況

全体的な状況はこんな感じらしい。

Django, Flask がやはり人気があるようだが、 これらは URLルーティング + ORマッピングなデザインだから 個人的には興味がない。

ただし、Django には GeoDjango というものがあるようで、 これは DB に PostGIS などを用いて空間情報を扱えるようにした 拡張らしい。暇で暇で仕方が無いような時があったら調べてみよう。

オブジェクト指向(的)のフレームワークとしては

  • CherryPy
  • Grok, Dolmen
  • Pyramid, Substance D

が見つかった。

CherryPy

PythonのWebフレームワーク「CherryPy」 に依ると、これはURL解決にトラバース方式を採用している。

データベースについてはフレームワークとして何もサポートしていないようで、 自分で好きなものを選んで自力で使え、ということのようだ。 例えばこの チュートリアル では sqlite3 をインポートして直接 SQL を投げている。 PyPI に CherryPy 用 SQLArchemy ツールがあるので、 そういうものを組み込めばいいのか。

Zope だとデータベースへのアクセスはフレームワークが一手に処理してくれて、 それに慣れていると、自分でデータベース周りのコードを書かなくちゃいけないのは 不安で仕方ない(トランザクション処理とかが不十分になりそうで)。

最新版は 3.6.0 (2014-09-14)。

Grok, Dolmen/Cromlech

Zope 3 の発展系。

Grok は Zope 3 に対して

  • ZCML を減らす(代わりに python コード中に書く)
  • ファイル構成やクラス名などに関する暗黙の規約を導入する

という変更を加えたもの。ZTK の上に grokcore.* とか megrok.* とかの ラッパーをかぶせている、という感じか。

この変更が便利かどうかは場合によるような気がする。ZCML は コントロールをモデルとビュー(python コード)から分離するのに良い仕掛けであると 思うのだが、まぁ確かに面倒と言えば面倒くさい。 単純なアプリを作るんだったら混ぜこぜの方が楽かも知れない。

Dolmen/Cromlech は Grok を元に派生した亜種で、 公式サイト に拠ると、implementaion と definition の厳密な分離を指向しているらしい。 詳細な記述がないので精確な意味は理解できないが、Zope 3 の開発経験から 想像するに、モデルとビューの役割分担が曖昧なところを問題視しているのだろう。 http request を受けて処理するのはビューなので、データ処理コードは ついついビューに書きがちで、モデルの内部構造に依存したコードを 書いてしまう。つまりカプセル化を軽視してしまう傾向がある。 Dolmen/Cromlech がこれをどのような方法で回避しようとしているのか、 サンプルコードもチュートリアルも見当たらないので解らない。

現在の開発状況はよく解らない。 専用の PyPI らしきところを見ると、細々とアップデートされているようだが。

Pyramid, Substance D

Pyramid は Django や Zope にインスパイアされた折衷的フレームワークで あるらしい。Django のように URLルーティング + ORマッビング方式にもできるし、 Zope のようにトラバーサル + オブジェクト指向DB にもできる。 Grok のようにデコレータを使ってもいいし、Zope のように ZCML で コントロールすることもできる。

特に、ZODB に対応しており、プロジェクト生成時に選択できることは 個人的には重要な点である。

開発は活発で、ユーザも多そうだ。ただし Zope 的に使っている人が どれくらい居るのか不明。

Substance D は、Pyramid 上で動くアプリケーションサーバで、公式サイトで 記されている通り、 Zope 2 に似ている。 データベースには ZODB を使うようだ。

正式リリース版というものは存在せず、ひたすら Github 上で開発が続いている らしい。既に充分に実用的なのだろうか。ユーザがどれだけ居るのかも 判らない。

っと、twitter に “#SubstanceD release coming soon” と流れているな。

]]>
Fri, 17 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/15/ms_mht.html http://blog.emaita.jp/2015/04/15/ms_mht.html <![CDATA[Microsoft MHTML 分解]]> Microsoft MHTML 分解

MS-WORD で保存したという mht ファイルを受け取ったのだが、 手元の Word for Mac 2011 で開けない。

../../../_images/word_error.png

中身を less で覗いても、壊れているようには見えなかったので、 ソフトウェアの問題なのであろう。WORD に拘る必要も無いし、 簡単に使える分解ツールは無いものかとググっても、めぼしいものが見つからず、 自分で書いた方が早そうだったので、そうした。

#!/usr/bin/python
# encoding: utf-8

import os
import sys
import errno
import email

# ファイル名が格納されているフィールド
TOJ = 'Content-Location'

# 抽出するべきデータ型
TYPES = {"text/html", "image/jpeg"}

# 出力先
OUTDIR = "mht_contents"

# 出力先作成
try:
  os.mkdir(OUTDIR)
except OSError, e:
  if e.errno != errno.EEXIST:
    raise RuntimeError

# ファイル読み込み
with open(sys.argv[1], "r") as fin:
  msg = email.message_from_file(fin)

# マルチパート解析
for mpart in msg.get_payload():

  # content type で選別
  if mpart.get_content_type() not in TYPES:
    continue

  # 出力ファイル名を抽出
  fn = mpart[TOJ].split("/")[-1]

  # ファイル出力
  with open(OUTDIR + "/" + fn, "wb") as fout:
    fout.write(mpart.get_payload(decode=True))

ファイルで欲しければ ここ から持っていくと良い。 第一引数で mht ファイル名を与えるようになっている。 まぁ、見れば解るか。Python 3 で動くかどうかは知らない。

]]>
Wed, 15 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/15/lv.html http://blog.emaita.jp/2015/04/15/lv.html <![CDATA[lv の仕様]]> lv の仕様

pretty でない(改行を含まない)XML ファイルを less (と言うか lv ) で表示させたら、 行の途中で勝手に改行されているように表示されて、なんじゃこりゃとびっくりした。 最初はファイルが壊れているのかと思ったが、wc で見るとそんなことはなく、 オリジナル less と lv の表示を比較してみて、lv がおかしいことが判った。

おかしいと言うか、 仕様 なのだなこれは。 多言語化less として結構長いこと lv を常用してきた筈だが、 今まで気付かなかった。どうしてだろう、不思議だ。

]]>
Wed, 15 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/14/emlsend.html http://blog.emaita.jp/2015/04/14/emlsend.html <![CDATA[EML送信コマンド自作]]> EML送信コマンド自作

トムソンロイター社に DCI 用の情報をメールで送ることになったので、 メール送信用のスクリプトを書く一日。昨日の午後に仕様を考え始めたが、 よくよく考えると結構複雑な動作が必要で、普段あまり使わないモジュールを 調べたりして、結局今日一日をコーディングに費やしてしまった。 200行くらいではあるが、 argparse でコマンド的な動作をするようにしたり、 頭の体操になった。

定期的にコードを書いてる訳ではなく、必要に応じて必要な分だけ書く、という 状況なので、それなりのものを作ろうと思うと最初にリハビリが必要になる。 昨日、仕様を考えながら、python っぽい書き方を思い出すのに苦労した。 まぁ、多分またすぐに忘れるだろうが。

正常系は完成したので、一晩寝かせてから異常系のテストをしよう。

]]>
Tue, 14 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/13/doukou.html http://blog.emaita.jp/2015/04/13/doukou.html <![CDATA[『学術の動向』 2014.11 (2)]]> 『学術の動向』 2014.11 (2)

研究データベースとか研究データ管理に数年間携わってきて、その結果、 これは 9割方は金の問題だ、と思うようになった。しかし私は世間知らず なので金の話がピンと来ない。

積ん読の「学術の動向」の続きを読んでいたら金の話が出てきたので ちょっとメモしておく。

文科省・学術情報基盤実態調査 によると、国内の大学における平成25年度の総計で、

図書館資料費:700億円
洋雑誌購入経費:100億円
電子ジャーナル経費:250億円

国研等の分も含めると日本全体でジャーナルに 400~500億円くらい支払っていて、 全世界だと数千億円規模の産業ということなのか。なるほど誰も彼もが シリアルズ・クライシスとぼやく訳だ。

理研・玉尾氏の、日本発国際誌の育成に関する記事 は興味深かった。 学術誌に対する費用に関して国家収支を考えると、日本から海外に流出する一方であり、 早急に評価の高い国際誌を育成して少しでも収支を改善しないといけない、という 分析。 仮に日本からの発表論文がすべて掲載料著者負担式だったとすると掲載料は 年間 110億円程度となり、これが外国に流出するか国内に還流されるかは 国家戦略上無視できない、ということらしい。 なるほど。そういうことは考えたことがなかったな。

]]>
Mon, 13 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/10/doukou.html http://blog.emaita.jp/2015/04/10/doukou.html <![CDATA[『学術の動向』 2014.11]]> 『学術の動向』 2014.11

データペーパーを 1件片付けたと思ったら別のリクエストが飛んできた金曜日。 1年前のことなんかすぐには思い出せないょぅ… うむ、よろしい、来週にしよう。

現実逃避に積ん読の「学術の動向オープンサイエンス特集号」を読み始める。

JST 中村理事長の記事に、2014年度中に「科学技術情報委員会」から データシェアリングの在り方について提言を出す、とあるが、 JST のウェブサイトに行ってもそれらしきページが見当たらないのだが、 これはスケジュールが遅れているのか? 12月2日の時点ではまだ検討中のようだが。 NDL 第5回科学技術情報整備審議会議事録 ググってもこれ以上の情報は出てこないなぁ。

NISTEP 林氏の記事に「自分社会系」という用語が出てきて、 何だこりゃ聞いたこと無いけど何か凄そうな用語だなぁ、 サブカル分野の新概念か? と一瞬思ってググってしまったが、単に「人文社会系」の typo のようだ。 がっかりだ。と言うか、一瞬でも「何か凄そう」と思ってしまった自分の サブカル脳を批判しなければならない。

]]>
Fri, 10 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/09/dwc_occurrence.html http://blog.emaita.jp/2015/04/09/dwc_occurrence.html <![CDATA[DwC Occurrence (2)]]> DwC Occurrence (2)

dwc_occurrence.xml の記述を JDC に取り込むコードを書いた。 そして実際に取り込んでみて、 データペーパーのデータファイルと項目数が一致しないことに気付いた。 dwc_occurrence.xml の方が項目が多い。具体的には以下の項目。

  • materialSampleID
  • infraspecificEpithet
  • taxonRank
  • verbatimTaxonRank

ファイル生成に使用したソフトウェアが古いバージョンだったのか。 まぁ4カラム程度だったら手作業で調整すればいいが、データファイルと定義が 一致するかどうかは毎回確認しないといけないな。

]]>
Thu, 09 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/08/dwc_occurrence.html http://blog.emaita.jp/2015/04/08/dwc_occurrence.html <![CDATA[DwC Occurrence]]> DwC Occurrence

dwc_occurence.xml の内容を JDC用に整理・加工している間に、 Darwin Core が随分複雑になっていることに驚いた。 地質年代の項目があるのは化石標本を扱うためか。こんな項目があるなんて 今まで知らなかったが、確かに化石も扱えないといけないよな。 DwC はシンプルなメタデータ標準だ、という風に 思い込んでいたが、いつの間にか、あるいは実は前から? 私の想像以上に 複雑な内容になっていたようだ。 まぁその大半が optional ではあるが、アプリケーションを組む側は optinal を含めて全ての項目を扱えるようにしなければならない訳で、 IPT の開発者とかは大変そうだな、とも思うが、今のところ他人事なので どうでもいい。

]]>
Wed, 08 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/07/dwca.html http://blog.emaita.jp/2015/04/07/dwca.html <![CDATA[Darwin Core Archive]]> Darwin Core Archive

ちょっと時間が掛かりそうだなこれ、と思ったのでしばらく放置していた データペーパーの処理を始める。

機械的に生成したデータファイルっぽい、というところまでは解る。 おそらく IPT が吐き出したんだろう。メタデータの先頭部分に http://rs.tdwg.org/dwc/terms/Occurrence とあるので、おそらく 観察データ用のフォーマットなのだろうと推測するが、なかなか定義を 見つけられなかった。生物多様性関係は情報量が多いから門外漢は難儀する。

データファイルを見ると、全部で 159カラムのうち、データが入っているのは 18カラムだけで、あとはひたすら空欄になっている。随分ムダなことをする。 optional な空カラムも律儀に出力するのは機械生成だからか、それとも GBIF の流儀なのか。多分、meta.xml や、データファイルのヘッダ行が 無くても困らないようにフォーマットを固定しているんだろうなぁ。

meta.xml を処理する方法は無いものかと色々ググってみたら PyPI に python-dwca-reader なるものを発見! これはいいものを見つけたぞ、 と思ってちょっと使ってみたが、動作が遅い。まぁいきなり 10万行の データを読み込ませたらメモリスワップするよな。機能的にもほとんど パーサ程度の機能しか無さそうだったので、今回の作業には使えないと 結論づけた。

その後、 http://rs.gbif.org/core/dwc_occurrence.xml を探し当てる。 TDWG じゃくて GBIF の方にあったのね。これを元にして EML の <attribute> を生成するスクリプトを組めば良い。 流用できそうなのは definition だけだろうが、何も無いよりはましだ。 それ以外は EML の仕様上ほとんど一意に定まる筈だし。

]]>
Tue, 07 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/07/openscience.html http://blog.emaita.jp/2015/04/07/openscience.html <![CDATA[内閣府オープンサイエンス検討会報告書]]> 内閣府オープンサイエンス検討会報告書

内閣府・国際的動向を踏まえたオープンサイエンスに関する検討会では、 昨年末から、世界的なオープンサイエンスの潮流に対して日本はどう 対応するべきかに関して議論が進められていたが、3月30日付けで 報告書が公表された。 (内閣府)

軽く目を通したので要点を幾つか。

  • 論文の根拠データは原則公開、それ以外のデータの公開は努力目標。
  • 競争的及び公募型研究資金による研究が対象。サマリでは言及されていないが、 報告書全文では全額運営費交付金による研究も対象とすべきとされている。
  • 大学・研究機関等は研究データの管理保存に関し、規則を定めて具体的施策を 実施すること。

他に気になった点は、

  • 「研究データは原著論文と同等又はそれ以上の研究開発成果として位置づけられ」 (p.15)

    データ公表が論文以上の成果になる文化っていうのは俄には信じがたい。 それは「科学とは知の集積である」という科学観が変更されるという ことを意味するだろう。更に敷衍すれば、論文よりもデータが評価されるなら、 データよりもそのデータを生み出す観測機器の開発の方がより評価される べきで、科学者よりも測器会社の技術者の方がより評価されるべきである、 ということになる(これは個人的に以前から疑念に思っていたことである。 現代の自然科学において観測機器の発展が占める比重があまりにも大きすぎる)。

  • 「データサイエンティスト等の育成と活用」(p.22)

    これは「育成と雇用」とするべきである。

    この手の分析では一般にデータ専門家の人材「育成」が課題として 挙げられることが多いが、私見では、人材育成は大した問題ではない。 問題はその後、専門職としての雇用があるかどうかで、日本でかつて 大学院重点化で院生を増やした後に何が起こったかはこの業界に居る 人間ならば誰でも知っていることであろう。

    この次の行に「人材の確保」という文面があるが、これも 「人材を雇用するための予算の確保」とする方が正しかろう。 「人材の確保」という表現では、予算はあるけど適当な人材が見つからない、 つまり人材の方が希少財のような感じを受けるが、実際は逆で、 求職者は掃いて捨てる程居るのに雇用する予算が無い、という状況の方が 支配的なはずである。

    人材育成は雇用とキャリアパスが伴わなければ効果が無い。 そして、雇用の維持とキャリアパスの確立の方が明らかに難しい問題なのである。

]]>
Tue, 07 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/03/trdci.html http://blog.emaita.jp/2015/04/03/trdci.html <![CDATA[DCI は有料サービスです]]> DCI は有料サービスです

所内から Web of science に接続してあちこち探したものの、 Data Citation Index の影も形も見当たらない。

あれ、もしかして、DCI って別途契約しないとアクセスできないのでは? と思って所の図書室に問い合わせてみたら、やはりそうで、 弊所では DCI を契約しておらず、当面はその予定もない、と返事が来た。

それ自体はまあ仕方が無い。無い袖は振れん。

問題なのは、では一体 DCI の利用者はどのくらい居るのか、というところで、 もし DCI の利用者が少ないんであれば、DCI に登録するメリットがあんまりない、 ということになる。 どの研究機関も学術出版に対する出費を少しでも減らそうとしている このご時世に、追加で DCI を契約する余裕のあるところがどれだけあるのか、 という疑念が湧かざるを得ない。DCI の料金が具体的にどれだけなのかは 知らないので判断できないが、少なくともどこでも気軽に買えるほど 安くはないのだろう。

DCI に登録すれば劇的にアクセスが増える、というような代物ではない、 ということは間違いなさそうだ。 そう考えるとやる気が萎むなぁ。

]]>
Fri, 03 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/02/datacite_std.html http://blog.emaita.jp/2015/04/02/datacite_std.html <![CDATA[DataCite citation standard]]> DataCite citation standard

DataCite のメタデータには必須項目が全部で 5つあって、

  • Identifier
  • Creator
  • Title
  • Publisher
  • PublicationYear

その必須項目を

Creator (PublicationYear): Title. Publisher. Identifier

という書式で並べることを DataCite は好ましいとしており、 この書式を DataCite citation standard と呼んでいる、という、 単にそれだけのことであるらしい。

参考— DataCite Metadata Schema Version 3.1

]]>
Thu, 02 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/02/dci_repo.html http://blog.emaita.jp/2015/04/02/dci_repo.html <![CDATA[DCI リポジトリ検索]]> DCI リポジトリ検索

MASTER DATA REPOSITORY LIST で DCI に収録されているリポジトリが検索できるようだ。 試してみる。

ecology:該当なし
ecological:US LTER
biodiversity:TaiBIF(台湾のGBIF組織)

あと KNB や台湾林業試験所も入っているっぽい。 今のところ生態学/生物多様性関係の収録数は少なそうだ。

Japan:MassBank(質量分析DBらしい)、 PODB3(植物オルガネラDB、基礎生物学研究所)、 SDBS(有機化合物スペクトルDB、産総研)

日本から参加しているのは現状この 3つだけのようだ。 JBIFとかはどうなってるんだろう。何か対応を考えているのか、 それとも話が行ってないのか。

]]>
Thu, 02 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/02/trdci.html http://blog.emaita.jp/2015/04/02/trdci.html <![CDATA[DCI (2)]]> DCI (2)

続き。

記事内容

TR社は三大分野(自然科学と技術、社会科学、人文科学)から 研究データを集める。個々のリポジトリが multi-disciplinary なのか inter-disciplinary なのか特定の分野に特化しているのかは問わない。

国際的多様性

国際的な利用者に情報提供するため、TR社はリポジトリの国際的多様性を 求めているけれども、その一方で地域的な研究活動にも適切に配慮する。 リポジトリの対象範囲の大小(国際的、国単位、地域、機関)によらず、 また多分野か特定分野特化なのかによらず、すべてのリポジトリに対して 一貫した基準で選別を行う。

データの引用と標準

研究コミュニティはデータの引用と帰属を調べたいと強く望んでいるものの、 一貫した標準は存在しないし、研究論文の引用文献一覧にデータが記載されることは 稀である。 これを解決するため、TR社は各レコードに標準化された引用書式を提供し、 データ引用を促進する。引用書式を決める際には多数の既存標準を評価した。 その結果、TR社は DataCite の引用標準を採択した。というのも、これは 一般的に支持されており、データの種類や分野を問わず適用可能な能力を 持っているからである。

データ引用及び、リポジトリ内容と文献のリンクはTR社と研究コミュニティにとって 重要な地位にあるため、格納データの引用・被引用に関する参照を提供する リポジトリには優先権が与えられる。

リポジトリの推薦

特定のリポジトリを採録するように推薦したい場合は、 詳しい情報をメールで知らせてくれ。

(ここまで)

DataCite citation standard って何なんですかねぇ。 TRに対して自薦することもできるらしいな。

]]>
Thu, 02 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/04/01/trdci.html http://blog.emaita.jp/2015/04/01/trdci.html <![CDATA[Thomson Reuters DCI]]> Thomson Reuters DCI

今日から本気出す、と毎日のように決意を新たにしております。

さて棚上げしてあった DCI 事案であるが、まずは情勢を精確に把握するために 資料を集めることに。 ウェブにTR社の資料があるのでまずそれを読む。

REPOSITORY EVALUATION, SELECTION, AND COVERAGE POLICIES に目を通していたら、幾つか興味深いことが書いてあった。 今後、DCI について他人に説明するよう命じられるかも知れないので、 メモを残しておく。

まず TR社としては、データであれば何でもいいという訳ではなく、 DCI に収録するべきリポジトリを選別しているようだ。 向こうからの最初のメールに “JaLTER has been selected as a potential resource…” って書いてあって、まるで詐欺メールの「当選おめでとうございます!!!!!!」 みたいな文面だな、と胡散臭く思ったが、TR社としては真面目に選別しているようだ。 その評価基準が幾つか挙げられている。英語苦手なので和訳する。

永続性と持続性

リポジトリ及びその中のデータの永続性(persistence)は、基本的な評価基準である。 DCI への取り込みが検討されるのは、長期的な維持が明示されているリポジトリだけである。 TR社はまた、新しいデータが現在も預託されているかどうかも吟味する。 つまり、新しいデータが継続的に預託されているということは、そのリポジトリが 現在もアクティブであることの証拠となる。 一般には、データそのものもリポジトリに預託される方が良い、 リポジトリにデータそのものを置かずに外部にあるデータへのリンクだけを登録する よりも。と言うのも、引用の集計やデータ再利用を考えた時に、より頑強な引用が できるからである。 データの公開プロセスは、理想的には、データ提供者・制作者の所属情報とともに はっきりと記載されるべきである。 リポジトリが採択されたら、そのリポジトリ内の全データは DCI に収録する。 サブリポジトリのデータも同様に収録するが、データそのものが預託されていないものは 除外とする。

資金の明示

DCI は、データの引用の促進、及びデータと研究文献を結びつけることを目的としている。 その目的のために、文献の来歴や研究費の情報を表示するリポジトリに対して 格別な配慮を与える。

英語のメタデータ

英語は現時点の科学において共通語である。 そのため TR社は、メタデータを英語で公開しているリポジトリや、 少なくとも十分な情報を英語で供給することができるリポジトリに関心がある。 DCI が収録しているリポジトリの中には、メタデータのみ英語で公開して 実際のデータは他の言語を使用しているものもある。 しかしながら、ゆくゆくは、国際的研究コミュニティにとって最重要なリポジトリが 英語でデータを公開するであろうことは明白である。特に自然科学においては間違いない。 更に言えば、全てのリポジトリはローマアルファベットで書かれたメタデータと引用を 保持しなければならない。 (英語化が無理ならせめてアルファベットにしろということか)

ピアレビュー

預託データのピアレビューは決して普遍的ではないものの、 ピアレビュープロセスの適用はリポジトリの基準の明示であり、 格納しているデータや引用された参照の完全性について全般的な品質の表明である。 また、可能ならばいつでも、リポジトリ、data studyやデータセットには その研究を支援した資金源の情報を付記することを推奨する。

材料の年齢

TR社はリポジトリと研究データの長期保存と持続性に基づいた判断をしなければならない。 従って、預託データの年齢に関しての制限は設けない。 多分野的サービスと同様に、 「古い」データに関しては分野ごとに研究者の態度や要求事項がまったく異なることが 知られている。 時流に乗っているかどうかも制限にはならない。 研究助成金を受けていたプロジェクトが終了する時のように、 価値のある研究成果が将来必ずしも更新されないであろうが、それにも関わらず それらが最新の研究で引用され続け、時には再利用されたりするかも知れない ということは認められることである。 また、著者や助成団体による猶予措置により、関連する研究論文に比べて データの公開が遅れることはあり得る。

研究文献へのリンク

データ引用のための標準を広めるため、そしてその結果として、学問における データ引用のインパクトを計測するために、 データセットとその研究文献の関連を示す来歴情報を提供するリポジトリには 優先権が与えられることになるだろう。

(ここまで)

JaLTER DB との関連だと、メタデータのみのパッケージや、研究助成や関連文献の 情報不足などが問題になりそうだ。 ER Data Papers の方もデータ登録のプロセスについてウェブサイトとかに ほとんど情報を出していない。 TR社の要求水準にちゃんと対応するにはそれなりに作業が必要になりそうだ。

]]>
Wed, 01 Apr 2015 00:00:00 +0900
http://blog.emaita.jp/2015/03/31/jdc_newsvr.html http://blog.emaita.jp/2015/03/31/jdc_newsvr.html <![CDATA[JDC サーバ切り替え]]> JDC サーバ切り替え

年度末だから、という訳でもないが、DNS を変更してサーバ切り替え。 事前の準備は抜かりないように色々考えるが、事後の作業はだいたい 忘れる。よくあるのは ssh の known_hosts の変更で、スクリプトが エラーを出すまで気付かないことが多々ある。まぁいつものことだ。

変更後のホスト構成。

  • www.emaita.jp
  • blog.emaita.jp
  • dosc.emaita.jp
  • jdc.emaita.jp
  • jdcdoc.emaita.jp
  • jdc-trial.emaita.jp
  • metacat-trial.emaita.jp

枯れ木も山の賑わいって感じだな。

]]>
Tue, 31 Mar 2015 00:00:00 +0900
http://blog.emaita.jp/2015/03/31/sakura_dns.html http://blog.emaita.jp/2015/03/31/sakura_dns.html <![CDATA[さくらインターネットのDNS設定]]> さくらインターネットのDNS設定

さくらインターネットにおける、 「会員メニューのドメイン設定」と「レンタルサーバのドメイン設定」の 関係についてのメモ。

これまで個人サーバとしてさくらのVPSを使用してきたが、 VPSだとシステムの入れ替えなどで長時間停止したり 引っ越ししたりしなければならず、ウェブページのような システム非依存のコンテンツは別にした方が楽かもなぁ、と思ったことが きっかけで、レンタルサーバを借りてみた。最安価の月額129円プラン。 ftps の設定がやや解り辛かったがググって解決。 えーと、一応張っておくか。ftp クライアントは lftp を使用。

set ftp:ssl-auth TLS
set ftp:ssl-force true
set ftp:ssl-allow yes
set ftp:ssl-protect-list yes
set ftp:ssl-protect-data yes
set ftp:ssl-protect-fxp yes
set ssl:verify-certificate no

さてそれはともかく、DNS の設定も変更しなければならない訳だが、 VPS の場合は「会員メニュー」のドメイン設定で、 レンタルサーバのマルチドメイン(バーチャルホスト)設定は レンタルサーバの「サーバコントロールパネル」のドメイン設定で 変更することになっており、両者の関係がよく解らなかった。

ちょっと試した結果、例えば blog.emaita.jp は、

  • 両方に設定しても、さくらのユーザインターフェイス上でエラー等は出ない。
  • 片方の操作は他方に影響しない。
  • 両方に設定するとレンタルサーバの設定の方が優先される。
  • 会員メニューの方は、 emaita.jp ゾーンの blog.emaita.jp エントリで、 レンタルサーバの方は、 blog.emaita.jp ゾーン の blog.emaita.jp エントリで、 別ゾーンということのようだ。
  • レンタルサーバの方に全く同じ emaita.jp ゾーンを作成するテストはしていない。 その場合はエラーになるのかも知れない。

ちょっとすっきりしない気がするが、会員メニューのドメイン設定には エントリ数上限がある(契約台数あたり5エントリ)ので、 レンタルサーバ側で処理できると余裕ができる。 レンタルサーバのマルチドメイン(バーチャルホスト)に上限があるのか どうかは判らない。ヘルプに書いてないから無限にできるのか?

]]>
Tue, 31 Mar 2015 00:00:00 +0900
http://blog.emaita.jp/2015/03/31/jdb_histrory.html http://blog.emaita.jp/2015/03/31/jdb_histrory.html <![CDATA[JaLTER データベース略史]]> JaLTER データベース略史

同じ仕事を何年もしていると、過去の出来事の時系列が不確かに なってくる。時々整理しておく方がいざという時に慌てなくて良い。

2006年末:JaLTER 設立。研究データベースの開発運用をミッションのひとつに謳う。
2007年度:環境省・環境技術開発等推進費「森林・草地・湖沼生態系に共通した 環境監視システムと高度データベースの構築」から システム構築の予算を確保。
2007年7月:台湾での ILTER-EAP 情報管理ワークショップに参加し、 EML処理系に関する情報を収集。JaLTER データベースを EML処理系で構築する方針を固める。
2007年後半:JaLTER データベースのプロトタイプ構築。
2007年末?:国立環境研究所・地球センターに機材を搬入、設置。
2008年1月:JaLTER 関係者を対象に講習会を開催(東大・弥生)。 以降、年1回程度頻度で継続。
2008年3月:JaLTER データベースの試験運用開始。 JaLTER 関係者向けの限定公開とする。
2009年3月:「JaLTER Network におけるデータポリシー」策定。
2009年10月:JaLTER データベースを一般公開。
2009年末頃:JaLTER Data Center 開発に取りかかる。
2010年夏頃:Morpho の多言語化に際して日本語メッセージファイルを開発チームに 提供、Morpho 1.9.0 に取り込まれる。
2011年3月:日本生態学会の英文誌 Ecological Research に Data Papers が 創設され、JaLTER データベースがそのリポジトリを提供することとなる。
2011年夏頃:ER Data Papers 専用サイトを開設。
2012年前半:JDC が実用レベルに達する。
2012年初夏:JDC の操作解説動画を作成し、Youtube に投稿。
2012年7月:JDC 運用開始。JaLTER データベースの標準入力ツールと位置づけ、 Morpho からの移行を計画する。
2012年9月:JaLTER の講習会で JDC の紹介と実習を行う。
2013年春頃:JDC 試用版サイトを開設。
2013年夏:日本生態学会誌に投稿したメタデータ作成に関する記事が掲載される。

過去のノートを引っ張り出せば細かい日付も判るはずだが、 そこまでする程のことではあるまい。

]]>
Tue, 31 Mar 2015 00:00:00 +0900
http://blog.emaita.jp/2015/03/25/morpho_ja.html http://blog.emaita.jp/2015/03/25/morpho_ja.html <![CDATA[Morpho 日本語メッセージ]]> Morpho 日本語メッセージ

昔の資料を整理しているのだが、Morpho のメッセージ日本語化について ちゃんと記録していなかったので、思い出しながらまとめておく。

そもそもの事情は、Morpho が多言語メッセージ化された時、 開発チームは当初 Google か何かの自動翻訳で日本語メッセージを作成したものの、 その翻訳が正しいのかどうなのか皆目判らないので、私の知り合いに 校閲を依頼してきたのだが、その知り合いは JAVA とか開発関係のことが まったく解らない人だっので、私が手伝うことになったのである。 ファイルのタイムスタンプを見ると 2010年夏になっているので、 たぶん Morpho 1.8.0 から 1.9.0 のあたりのことだろう。 手元に残っているメッセージファイルの行数は 633行で、 最新リビジョンだと 727行だから、数年間でだいぶ増えているな。 現在では個人的にも JaLTER としても Morpho から JDC に移行したので、 最新リビジョンのファイルを修正して開発チームに送るような 気力は湧かない。

以下、手順。

ソースコードをリポジトリから取り出す。

$ svn co https://code.ecoinformatics.org/code/morpho/trunk morpho_src

メッセージファイルは morpho_src/lib/language/ に配置されている。

$ ls morpho_src/lib/language/
Messages.properties         Messages_ja.properties
Messages_es.properties      Messages_pt.properties
Messages_fr.properties      Messages_zh_TW.properties

言うまでもなく、Messages_ja.properties が日本語用ファイルである。 ファイルのフォーマットは JAVA プロパティで、 エンコードはユニコードエスケープでなければならない。

世間ではユニコードエスケープを直接扱える「プロパティエディタ」なるものが あるらしいが、ここでは別にそんなものを使うまでもないので、 一旦 UTF-8 に変換して常用のエディタを使うこととする。 エンコード変換には native2ascii を使用する。 MacOS X の場合、もしかしたら X Code をインストールしないと使えないかも 知れない。

$ native2ascii -encoding UTF-8 -reverse morpho_src/lib/language/Messages_ja.properties > msg_ja.utf8

UTF-8 化したメッセージファイルを編集する。 編集が終わったらエンコードを元に戻す。

$ native2ascii -encoding UTF-8  msg_ja.utf8 > morpho_src/lib/language/Messages_ja.properties

Morpho のビルドには Apache Ant が必要だが、 Mac OS 10.9 からは Ant がベースシステムから除外されたらしい。そのため手動でインストールする。 野良でも brew でも Mac Port でもいいが、私は Mac Port を使っているので 以下のようにする。

$ sudo port install apache-ant

Morpho をビルドする。

$ cd morpho_src; ant macjarbundler

なお Windows 版をビルドするには

$ ant buildwinexe

とする。

ビルドされた Morpho を起動して修正したメッセージが適切かどうか確認し、 必要に応じて再修正を繰り返す。

]]>
Wed, 25 Mar 2015 00:00:00 +0900
http://blog.emaita.jp/2015/03/23/jdc_trial.html http://blog.emaita.jp/2015/03/23/jdc_trial.html <![CDATA[JDC 試用版引っ越し]]> JDC 試用版引っ越し

サーバ引っ越しメモの続き。 JDC 試用版用にメールとキャプチャと Metacat が要る。

メール

メール送信設定は、アカウント作成時にメールで通知するので送信機能だけ あればよい。postfix に切り替えて基本設定を調整する。

captchaimage

easy_install/pip だと依存ライブラリのヘッダファイルが見つけられなくてビルド失敗、 ports/pkg には収録されていないので、手動でビルドする。

tarファイルをダウンロード、展開後、setup.py の

include_dirs = ["/usr/include/freetype2"],

include_dirs = ["/usr/local/include/freetype2"],

に修正して

# python setup.py build
# python setup.py install

を実行する。

buildout は JDC と同様にすればよい。

Metacat

入力内容確認用。バージョンは 2.0.3。

Metacat は admin アカウントでさえも LDAP を使わないといけないのが 面倒だ。とは言え仕方ないので openldap をインストールして slapd を 動かす。slapd.conf に inetorgperson.schema を追加しておく。 ldapadd で inetOrgPerson クラスのアカウントを作成して ldappasswd で パスワードを付与。このアカウントは Metacat の admin として使用する。

次に Postgresql。サーバパッケージをインストールして initdb して ユーザ作成して DB 作成して権限付与する。

# pkg install postgresql94-server
# service postgresql initdb
# service postgresql start
# su pgsql
$ psql postgres
postgres=# create user metacat with unencripted password 'パスワード';
postgres=# create database metacat with owner metacat;
postgres=# grant all on database metacat to metacat;

Tomcat 7 は、インストール後、 conf/web.xml の setCharacterEncodingFilter の コメントを外して有効化する。

Metacat デプロイの準備として、バックアップディレクトリ作成。

# mkdir /var/metacat
# chown www:www /var/metacat

Metacat と Geoserver を Tomcat webapps に配置する。

Apache httpd の設定。初期状態では proxy_http や proxy_ajp がコメントアウト されているので、有効化し、Tomcat へのリバースプロキシを設定する。

Metacat の admin ページを呼び出して各種設定。

]]>
Mon, 23 Mar 2015 00:00:00 +0900
http://blog.emaita.jp/2015/03/13/jdc_moving.html http://blog.emaita.jp/2015/03/13/jdc_moving.html <![CDATA[JDC 引っ越し]]> JDC 引っ越し

玉突き的にサーバ引っ越し中。空き家になったサーバに FreeBSD 10.1 を 改めてクリーンインストールして、ウェブアプリ系を移動させる。

JDC が動かないと始まらないのでまずそれから。

最大の難点は distribute/setuptools の開発状況の混乱で、 ネットの状況によると現在は setuptools に統合されているらしい。 そこで setuptools を使うことにしたのだが、生憎 ports/pkg に 収録されているバージョンが 5.5.1 とかなり古く、 これを使用すると buildout かなんかのバージョンチェックに通らなかった。 ports/pkg の setuptools は libxml2 などと依存関係にあるので setuptools だけ最新版を入れるというのも混乱の元になるから避けることとし、 一方 virtualenv では比較的新しいバージョン 12 がインストールされることから、

  • bluebream 環境の構築は virtualenv 環境下で実施
  • JDC は直にサーバ環境で実行

することに。

BlueBream 環境の構築

手順。

  • virtualenv 環境作成
  • 素の BlueBream プロジェクトで buildout の確認
  • JDC で buildout 実行
  • 設定等を実環境用に修正

virtualenv 環境作成

virtualenv インストール。

# pkg install py27-setuptools
# pkg install py27-virtualenv

easy_install 用に CA 証明書インストール。

# pkg install ca_root_nss-3.17.3_1
# ln -s /usr/local/share/certs/ca-root-nss.crt /etc/ssl/cert.pem

隔離環境を作成して切り替え。

$ virtualenv venv
$ source venv/activate

BlueBream buildout 確認

(venv)$ easy_install bluebream
(venv)$ paster create -t bluebream test
(venv)$ cd test
(venv)$ python bootstrap.py --setuptools
(venv)$ ./bin/buildout
(venv)$ ./bin/paster serve debug.ini
(Ctl-C)

BlueBream のコアが立ち上がって listen 状態になったら OK。

JDC で buildout 実行

JDC のソースを展開してトップディレクトリに移動。 たとえば、

(venv)$ svn export file:///svn/.../trunk jdc
(venv)$ cd jdc

そして buildout 実行。

(venv)$ python bootstrap.py --setuptools
(venv)$ ./bin/buildout

実環境用設定

virtualenv 環境から抜ける。

(venv)$ deactivate

bin/paster を修正。

#!/usr/local/bin/python     <- 修正
..snip..
  '/.../venv/lib/python2.7/site-packages/Paste-1.7.5.1-py2.7.egg',  <- トル

Paste 関連を実環境にインストールする。

# pkg install py27-Paste
# pkg install py27-PasteDeploy
# pkg install py27-PasteScript

JDC 実行環境の構築

JDC が使用する python ライブラリをインストールする。

# pkg install py27-libxml2
# pkg install py27-libxslt
# pkg install py27-imaging
# pkg install py27-dateutil
# pkg install py27-xlrd
# pkg install py27-openpyxl

Note

openpyxl はメジャーバージョンが上がっていた (1 -> 2) ので、 新バージョンでも動くか後で確認する。

JDC 起動テスト。

# ./bin/paster serve debug.ini
(Ctl-C)

Apache httpd の設定

リバースプロキシ、および、JDCに正しいURLを通知する設定を加える。 例えば、

ProxyPass /jdc/ http://localhost:8081/++vh++http:svr2.emaita.jp:80/jdc/++/
ProxyPassReverse /jdc/ http://localhost:8081/

メモ

画像ファイルをアップロードする時にエラーが出ることに気付いた。 後で調べる。

]]>
Fri, 13 Mar 2015 00:00:00 +0900
http://blog.emaita.jp/2015/03/12/freebsd_upgrade.html http://blog.emaita.jp/2015/03/12/freebsd_upgrade.html <![CDATA[FreeBSD アップグレード(10.1)]]> FreeBSD アップグレード(10.1)

基本的にクリーンインストール派なのでアップグレードはあまり使わないのだが、 後学のため、空き家になった旧サーバで最新のアップグレード手順の確認をした。

まず一応、パッチレベルを最新にする(10.0-p17)。

# freebsd-update fetch
# freebsd-update install
# reboot

その後、 10.1 にアップグレードする。

# freebsd-update upgrade -r 10.1-RELEASE
# freebsd-update install
# reboot
# freebsd-update install
# pkg upgrade
# freebsd-update install
# reboot

自動的に最新パッチがインストールされるらしく、 10.1-p6 になった。 install の実行数が2回から3回に増えているのは、

  • ユーザランドインストール
  • 不要ファイル削除

のプロセスを分離するためのようだ。3回目では古い *.so が削除されるため、 その前に ports のリビルドとかをしろということらしい。

ZFS 関係が改良されているためzfsストレージのアップグレードも必要だが、 省略。

ZFS に bookmarks という機能が追加されたらしい。これはスナップショットの メタデータだけを保存するという機能のようで、スナップショット自体を消した 後でもメタデータだけは残すように使うらしい。 つまり、データブロックは残ってないのでロールバックはできないが、 どのデータブロックが更新されたかは検出できるので zfs send で同期させる時の目印には使える、ということのようだ。

]]>
Thu, 12 Mar 2015 00:00:00 +0900
http://blog.emaita.jp/2015/03/11/sphinx_ext.html http://blog.emaita.jp/2015/03/11/sphinx_ext.html <![CDATA[Sphinx 自作拡張移植]]> Sphinx 自作拡張移植

新サーバ上で Sphinx の挙動がおかしいことに気付いて、 よくよく考えたら自作拡張を作った時に Sphinx 本体のコードに 手を加えたことを思い出した。

virtualenv で隔離環境を作ることにしよう。

# pkg install py27-virtualenv
# pip install sphinx

旧サーバと新サーバで Sphinx のバージョンが異なる (1.2.3 -> 1.3) ので 自作拡張用パッチが一部 rej された。マニュアルで修正。

libxml2 が pip でも easy_install でも入らないので、実環境のファイルを 隔離環境に無理矢理持ってくることにした。

# ln -s /usr/local/lib/python2.7/site-packages/libxml2mod.s
# ln -s /usr/local/lib/python2.7/site-packages/libxml2.py

これで以前と同じ挙動になった。

なお、easy_install で SSL 関係のエラーが出て中断する問題は、

# pkg install ca_root_nss-3.17.3_1
# ln -s /usr/local/share/certs/ca-root-nss.crt /etc/ssl/cert.pem

で回避できるようだ。 https://nixbsd.wordpress.com/2015/01/02/freebsd-ssl-certificate_verify_failed/

]]>
Wed, 11 Mar 2015 00:00:00 +0900
http://blog.emaita.jp/2015/03/10/bookreport.html http://blog.emaita.jp/2015/03/10/bookreport.html <![CDATA[湯本・松田『世界遺産をシカが喰う』]]> 湯本・松田『世界遺産をシカが喰う』

いろいろ資料を集めるのは楽しいんだけど、読むのがね。 主に気力的な面で。

湯本貴和・松田裕之編『世界遺産をシカが喰う シカと森の生態学』文一総合出版。 約10年前の本だが、今現在でもシカの食害が全国的に大問題であることは、例えば CiNii で「シカ 食害」と検索してみれば理解できる。 シカが人の手に負えないほど増えた理由は現時点で科学的には未解明であり、 解明される気配もなさそうに見えるんだが、実のところはどうなんだろう。 個人的には「天敵(オオカミ)が絶滅したからだ」という説を信じており、 オオカミを(トキのように)中華大陸から持ってくればいいんじゃないの、 と思ってはいるものの、真剣に検討した結果の意見ではないので 他人に強く主張するつもりはない。

武村政春『巨大ウイルスと第4のドメイン 生命進化論のパラダイムシフト』 講談社ブルーバックス、 面白そうなので買ってみたが、面白いようなそうでないような。 近年、巨大ウイルスなるものが発見されて話題になっているということは まったく知らなかったので勉強になった。それはそれとして後半の生命進化に 関する部分はちょっと空想的すぎて説得力を感じないなぁ。 細胞核の出現はウイルスの影響とかではなくて 有糸分裂の確立との関連の方が重要なのではないか。 と、この前読んだ高木由臣『有性生殖論』に強い感銘を受けたせいで そう思うのであります。 ちなみに生命・非生命の分別については池田清彦の影響で構造主義的生物学的な 立場に説得力を感じております。

]]>
Tue, 10 Mar 2015 00:00:00 +0900
http://blog.emaita.jp/2015/03/06/freebsd10_1.html http://blog.emaita.jp/2015/03/06/freebsd10_1.html <![CDATA[FreeBSD 10.1 導入]]> FreeBSD 10.1 導入

ずっと先延ばしにしていた OS バージョンアップを断行するのであります。 そうしないと Tinkerer の置き場が決まらない。

FreeBSD のリリーススケジュールは、

  • 10.2 — 2015年11月
  • 11.0 — 2015年7月

11.0 に手を出すつもりはないので 10.2 に着目すると、半年以上先の予定だから 今 10.1 にバージョンアップしてもそれほど悪いタイミングという訳ではない。 よろしい。

まずは気楽に作業できる開発機から。

クリーンインストール主義者なので、さくらVPS で新インスタンスを契約、 10.1 の ISO でブートさせて手なりのインストール。さくらVPS 側で カスタムOSを準備してくれると sftp put する手間が省けて楽なのだが、 未だに9系しか用意されていないというのは怠慢ではないのかね。 FreeBSD ユーザってそんなに少ないのか。まぁ少ないよね。

これまで pf を使っていたけど、これを期に ipfw に変えてみる。 初めて使うツールはやはり細かい所で躓くな。

  • ループバックと ip6 mandatory の設定は rc.firewall が勝手に設定するので ユーザは書かなくていい。
  • rc.firewall の自動設定にルール番号1000番まで消費されるので、ユーザは 1001番以降を使うと良い。
  • DNS, NTP は UDP を使うことを思い出せ。何で忘れるんだろうかねぇこういうこと。
  • udp 設定に keep-state オプションを付けると tcp established っぽい挙動になって便利。

Tinkerer は、

  • easy_install だと not found
  • pip だと lxml のコンパイルでコケるので、別途 pkg install py27-lxml すると通る

あとは概ねいつも通り。

]]>
Fri, 06 Mar 2015 00:00:00 +0900
http://blog.emaita.jp/2015/03/05/c5.html http://blog.emaita.jp/2015/03/05/c5.html <![CDATA[Concrete5 所感]]> Concrete5 所感

昨日は学術会議でデータジャーナルに関する講演会。 10人くらいが現状報告・情報提供して、現状認識を一致させて 問題意識を共有しましょう、という会だった。 議論の時間はほとんどなく、戦略的・建設的な話はなかった。 もしかしたらオフレコでやってたのかも知れないが。 でもまあ面白かった。現状把握という意味では有用だった。 あとで講演資料を学術会議のウェブサイトに載せるそうなので、 しばらくしたら見てみよう。

学術会議のロビーに学術の動向のバックナンバーが置いてあったので 暇つぶしに見てみたら、2014年11月号でオープンサイエンスが特集されているのを 見つけた。しばらくしたら J-Stage で無料閲覧できるようになるはずだが、 ページ数が多いので冊子を買ってもいい。あとでアマゾンでポチるか。 紀伊国屋が取り扱ってないのは何でだ。

今日は Concrete5 を試してみた。ウェブ上に転がっていたチュートリアルを 真似して Nifty C4SA というクラウド上で動かしてみた。 クリック一発でインスタンスができちゃうなんて、クラウド環境は楽ちんだなぁ。 まぁその分高いが。

  • ページ上の規定の位置(エリア)に各種コンポーネント(ブロック)を配置していって ページを作るというやり方。確かに初心者に優しい。
  • ブロックの種類は実用に充分なだけ揃っているようにみえる。
  • エリアの配置はテーマによって固定化されている。 エリアを調整するにはテーマファイルを改造しないといけない。 テーマは PHP で書かれているので、改造するには PHP をハックしないといけない。
  • 最新バージョン 5.7 に対応しているフリーのテーマはほとんどない。 5.6 用はいっぱいあるようだが。

テーマの問題さえ解決できればツールとして悪くないように思える。 今すぐ何かをしないといけない訳ではないので、しばらく様子を見よう。

]]>
Thu, 05 Mar 2015 00:00:00 +0900
http://blog.emaita.jp/2015/03/03/survey.html http://blog.emaita.jp/2015/03/03/survey.html <![CDATA[ウェブ作成ツール調査]]> ウェブ作成ツール調査

昨日から色々調べているが、何で調べ始めたんだったかな。 まぁいいや。

  • Concrete5 という CMS が楽しそう。あとで試す。 使えそうだったら JaLTER ウェブサイトの改装時に導入することを検討する。

  • Plone は ver. 5 が開発中、アルファ状態。 検索すると「2014年中にリリースか」という記事が出てくるが、 現時点でまだアルファ版ということは、 開発スケジュールが順調に遅れているということなのだろう。 たぶんあと半年は出ないな。

  • Zope の開発状況はよく判らなかった。 Zope 2 をベースにして Zope 4 を開発中という記事があった一方、 Grok や Pyramid も並行しているし、どうなってんだか。 相変わらず情報を探し難い。 https://zope.readthedocs.org/en/latest/WHATSNEW.html

    Plone の開発陣は将来的なフレームワークの選択に悩んでいるようだ。 https://plone5.veit-schiele.de/news/plone-2020

    どちらにせよ、 Zope 4 が Zope 2 の後継なら Zope 3 ベースの JDC には 関係ない話だ。Zope3(BlueBream) に関しては特に新しい情報はなかった。

  • Python ベースのブログ生成ツールとして tinkerer, pelican が 有力らしい。試しに Sphinx ベースの tinkerer を使ってみた。 というのがこのブログの動機。しばらく使ってみよう。

]]>
Tue, 03 Mar 2015 00:00:00 +0900