[python] KMLを生成するPythonモジュールsimplekml

KMLは、位置情報を表すためのXMLフォーマットで、GoogleMapsやGoogleEarthでも採用されています。AndroidアプリのデモのためにGPSをシミュレートしたいときなどにも使うことができます。
http://ja.wikipedia.org/wiki/KML

このKMLフォーマットを、Pythonから生成することができるsimplekmlモジュールの使い方を紹介します。

ドキュメント

ドキュメントへは以下のURLでアクセスできます。
http://code.google.com/p/simplekml/wiki/Welcome

インストール

pipでインストールすることができます。

sudo pip install simplekml

場所の登録

kmlインスタンスにnewpointメソッドでどんどん場所を追加していくだけです。結果のkmlを取得するには、kml.kml()というメソッドを使います。ファイルに保存したい場合は、kml.save()というメソッドを使うと便利です。

import simplekml

kml = simplekml.Kml()
kml.newpoint(\
    name="武蔵小杉駅",\
    description="神奈川県民だわー",\
    coords=[(139.6594757216514,35.57075039910515)]\
)
kml.newpoint(\
    name="六本木駅",\
    description="死にたい",\
    coords=[(139.72678679072163,35.66917008965268)]\
)
print kml.kml()

実行結果

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">
    <Document id="feat_1">
        <Placemark id="feat_2">
            <name>武蔵小杉駅</name>
            <Point id="geom_0">
                <coordinates>139.659475722,35.5707503991,0.0</coordinates>
            </Point>
            <description>神奈川県民だわー</description>
        </Placemark>
        <Placemark id="feat_3">
            <name>六本木駅</name>
            <Point id="geom_1">
                <coordinates>139.726786791,35.6691700897,0.0</coordinates>
            </Point>
            <description>死にたい</description>
        </Placemark>
    </Document>
</kml>

(応用) mixiチェックインの履歴を、GoogleMapsに表示する

冒頭でも述べましたが、GoogleMapsではKMLフォーマットをサポートしていて、クエリにKMLのURLを与えるとマーカーで表示してくれます。
これを利用して、mixiチェックインAPIが返すjsonKMLに変換する関数を書いたのが以下です。

#coding: utf-8

import simplekml
from datetime import datetime
try:
    import simplejson as json
except ImportError:
    import json

# input:    json string contains mixi checkin history
# output:   converted kml string
def mixicheckinjson2kml(json_string):
    data = json.loads(json_string)
    kml = simplekml.Kml()
    # create a new folder
    folder = kml.newfolder(name="mixi checkin history", description="mixi checkin history")
    for entry in data["entry"]:
        name = entry["spot"]["name"]["formatted"]
        message = entry["message"]
        latitude = entry["location"]["latitude"]
        longitude = entry["location"]["longitude"]
        created_at = convertdateformat(entry["created"])

        # create a new point
        folder.newpoint(\
            name=name,\
            description=message,\
            coords=[(float(longitude), float(latitude))],\
            altitudemode="relativeToGround",\
            visibility=1,\
            extrude=1\
        )
    return kml.kml()
        
# convert iso datetime format to kml date format
def convertdateformat(isoformatdate_string):
    s = isoformatdate_string.split("+")[0]
    d = datetime.strptime(s, "%Y-%m-%dT%H:%M:%S")
    return d.strftime("%a, %d %b %H:%M:%S")


###################
## test
###################
def main():
    import sys
    if len(sys.argv) < 2:
        usage()
    json_filename = sys.argv[1]
    json_string = open(json_filename, "r").read()
    kml_string = mixicheckinjson2kml(json_string)

    # save to .kml file
    f = open("output.kml", "w")
    f.write(kml_string)
    f.close()
    return 0

def usage():
    print "Usage: python mixicheckinjson2kml.py path/to/mixi_checkin_json_file"
    sys.exit(1)

if __name__ == '__main__':
    main()

注意点

simplekmlはPython2.6以降しかサポートしていないようで、2.5ではうまく実行することができませんでした。appengineで使う場合などには注意が必要です…

mixiチェックインの履歴をGoogleMaps上に表示するツール on appengine

http://mixi-api-dev.appspot.com/checkin-mapping

名鉄乗鉄王にITの力で挑んでみた 〜2011冬〜

9時から17時の間、電車を乗り継ぎ、下車駅名でしりとりをしていくというルールで行われました。詳細については一緒に行ったlabeneko先生の記事にまとめられています。
http://d.hatena.ne.jp/labeneko/20111225/1324825332

名鉄の駅はイベント開催時点で275駅あり、しりとりできるペアの数(名鉄一宮→山崎、名鉄一宮矢作橋名鉄一宮→弥富、…)はおよそ2200通りあります。

乗り継ぎ計画を組み立てるのは私ではlabeneko氏に絶対敵いませんが、人手だけで1からルートを検討しても、どうしても漏れが出てしまうのではないか?と考えました。そこで、プログラムで全パターンを計算したのち、文字数や総乗車時間などから現実的なルートを洗い出す試みに挑戦しました。

その結果、人ではなかなか思いつかないようなルートを出すことができ、実戦で活かすことができたので、そんなデータの作成手順を紹介しようと思います。

駅名一覧を作成する

漢字駅名と、しりとりに使うための平仮名表記を作成します。平仮名表記については、今回のルールで同一とみなされる濁音や拗音は統一しておきます。(例:「じもくじ」は「しもくし」で格納)

名鉄岐阜        めいてつぎふ
加納    かのう
茶所    ちゃじよ
岐南    きなん
笠松    かさまつ
木曽川堤        きそがわづつみ
黒田    くろた
新木曽川        しんきそがわ
石刀    いわと
今伊勢  いまいせ
しりとりが成立する駅名の全ペアを作成する

上記平仮名表記をもとに、しりとり可能な駅名のペアをスクリプトで作成します。このペアには、「ん」で終わっているものも含めます。(最後に行く可能性を考慮するため)
冒頭でも述べましたが、このペアがおよそ2200通り存在します。

名鉄岐阜        二ツ杁  めいてつぎふ    ふたついり
名鉄岐阜        富士松  めいてつぎふ    ふじまつ
名鉄岐阜        藤川    めいてつぎふ    ふじかわ
名鉄岐阜        福地    めいてつぎふ    ふくち
名鉄岐阜        二子    めいてつぎふ    ふたこ
名鉄岐阜        渕高    めいてつぎふ    ふちだか
名鉄岐阜        藤浪    めいてつぎふ    ふじなみ
名鉄岐阜        不破一色        めいてつぎふ    ふわいしき
名鉄岐阜        富貴    めいてつぎふ    ふき
名鉄岐阜        扶桑    めいてつぎふ    ふそう
ペア間の移動時間を追加する

ジョルダンの乗り換え案内サービスを利用して、各ペア間の移動時間を取得します。
もちろん、何時に出発するかによって移動時間は異なりますが、簡略化のために全ての駅を午前10時に出発した場合の時間を追加しています。例えば名鉄岐阜-不破一色間が21分かかるのであれば、

名鉄岐阜        不破一色        めいてつぎふ    ふわいしき      21

というtsvを出力します。

ルート探索

作成したペアと所要時間のデータを使うと、出発点を与えればそこから辿れる駅を再帰的に探索していくプログラムを書くことができます。あまりに長いルートは現実的ではないため、総乗車時間や総駅数に閾値を決めておき、超えた時点で探索を終了するようにしておきます。
そのようにして得られた探索結果は以下の形式で出力しており、条件に合わせて駅名でgrepしたり、乗車時間でソートしたりすると、それっぽいルートがずらっと出るようになります。

総文字数    総駅数    総乗車時間(分)    駅名1    駅名2    …
110     18      377     半田口(0,5)     知多半田(3,5)   巽ヶ丘(16,6)    金山(22,4)      丸ノ内(15,5)    中京競馬場前(39,14)     榎戸(66,4)      常滑(4,4)       名鉄一宮(48,9)  山崎(16,4)       木曽川堤(31,7)  妙興寺(22,6)    島氏永(2,6)     苅安賀(22,5)    観音寺(1,5)     新清洲(24,5)    須ケ口(2,4)     中部国際空港(44,12)
110     18      379     半田口(0,5)     知多半田(3,5)   高横須賀(23,6)  金山(17,4)      丸ノ内(15,5)    中京競馬場前(39,14)     榎戸(66,4)      常滑(4,4)       名鉄一宮(48,9)  山崎(16,4)       木曽川堤(31,7)  妙興寺(22,6)    島氏永(2,6)     苅安賀(22,5)    観音寺(1,5)     新清洲(24,5)    須ケ口(2,4)     中部国際空港(44,12)
106     18      379     三河八橋(0,7)   新安城(12,7)    宇頭(3,3)       牛田(15,3)      大山寺(53,5)    新日鉄前(54,8)  榎戸(30,4)      常滑(4,4)       名鉄一宮(48,9)  山崎(16,4)      木曽川堤(31,7)   妙興寺(22,6)    島氏永(2,6)     苅安賀(22,5)    観音寺(1,5)     新清洲(24,5)    須ケ口(2,4)     中京競馬場前(40,14)
105     17      374     知多半田(0,5)   巽ヶ丘(16,6)    金山(22,4)      丸ノ内(15,5)    中京競馬場前(39,14)     榎戸(66,4)      常滑(4,4)       名鉄一宮(48,9)  山崎(16,4)      木曽川堤(31,7)   妙興寺(22,6)    島氏永(2,6)     苅安賀(22,5)    観音寺(1,5)     新清洲(24,5)    須ケ口(2,4)     中部国際空港(44,12)
105     17      374     半田口(0,5)     知多半田(3,5)   巽ヶ丘(16,6)    金山(22,4)      丸ノ内(15,5)    中京競馬場前(39,14)     榎戸(66,4)      常滑(4,4)       名鉄一宮(48,9)  山崎(16,4)       木曽川堤(31,7)  妙興寺(22,6)    島氏永(2,6)     観音寺(20,5)    新清洲(24,5)    須ケ口(2,4)     中部国際空港(44,12)
105     17      376     知多半田(0,5)   高横須賀(23,6)  金山(17,4)      丸ノ内(15,5)    中京競馬場前(39,14)     榎戸(66,4)      常滑(4,4)       名鉄一宮(48,9)  山崎(16,4)      木曽川堤(31,7)   妙興寺(22,6)    島氏永(2,6)     苅安賀(22,5)    観音寺(1,5)     新清洲(24,5)    須ケ口(2,4)     中部国際空港(44,12)
105     17      376     半田口(0,5)     知多半田(3,5)   高横須賀(23,6)  金山(17,4)      丸ノ内(15,5)    中京競馬場前(39,14)     榎戸(66,4)      常滑(4,4)       名鉄一宮(48,9)  山崎(16,4)       木曽川堤(31,7)  妙興寺(22,6)    島氏永(2,6)     観音寺(20,5)    新清洲(24,5)    須ケ口(2,4)     中部国際空港(44,12)
105     17      377     尾張横須賀(0,7) 金山(14,4)      丸ノ内(15,5)    中京競馬場前(39,14)     榎戸(66,4)      常滑(4,4)       名鉄一宮(48,9)  山崎(16,4)      木曽川堤(31,7)  妙興寺(22,6)     島氏永(2,6)     苅安賀(22,5)    観音寺(1,5)     甚目寺(36,4)    新清洲(15,5)    須ケ口(2,4)     中部国際空港(44,12)
105     18      378     三河八橋(0,7)   新安城(12,7)    牛田(3,3)       大山寺(53,5)    神宮前(27,6)    榎戸(44,4)      常滑(4,4)       名鉄一宮(48,9)  山崎(16,4)      木曽川堤(31,7)  妙興寺(22,6)     島氏永(2,6)     苅安賀(22,5)    観音寺(1,5)     甚目寺(36,4)    新清洲(15,5)    須ケ口(2,4)     中京競馬場前(40,14)
104     18      366     三河八橋(0,7)   新安城(12,7)    宇頭(3,3)       牛田(15,3)      大山寺(53,5)    神宮前(27,6)    榎戸(44,4)      常滑(4,4)       名鉄一宮(48,9)  山崎(16,4)      木曽川堤(31,7)   妙興寺(22,6)    島氏永(2,6)     苅安賀(22,5)    観音寺(1,5)     新清洲(24,5)    須ケ口(2,4)     中京競馬場前(40,14)
データダウンロード

犬山遊園」「八幡新田」で終わるルートの一部(20KB)
http://dl.dropbox.com/u/231552/meitetsu/meitetsu_routes_top100_n.tsv

使用データフルセット(2.7MB、展開後59.2MB)
http://dl.dropbox.com/u/231552/meitetsu/route_1225.tgz

反省点

反省点としては、出力されるルートの数が多すぎて結局検証に手間がかかるという点が挙げられます。ルートが多すぎると、大雑把な条件でgrepしていくことになりますが、今度はそれで省いてしまったルートに、実は優勝できそうなルートが紛れていたのでは?ということが起こります。やはり出発時刻に応じて、下車駅での待ち時間も考慮した移動時間を計算する必要があるかもしれません。

SphinxでS6のスライドを作る

プライベートで最近開発したものなどを発表する会を同期とやろうっていう話になって、スライドを作る機会があったんで使ってみた。rest書くの自体卒論ぶりなんでSphinxのインストールから書く

環境はUbuntu 11.10

1.Sphinxのインストール

sudo apt-get install python-sphinx

sphinx-quickstartが実行できるようになっていればOK。

2.docutilsのインストール

sudo easy_install docutils

3.S6用テーマのインストール

sudo easy_install sphinxjp.themes.s6

4.スライドを書く

表紙タイトル
================

タイトル
--------------

* hoge
* funi

タイトル2
--------------

* foo
* bar

など。書けたら*.rstという拡張子で保存しておく

5.sphinx-quickstart実行

対話式で進めていく。わからないところはデフォルトでEnterして問題ない

6.conf.py編集

conf.pyがカレントディレクトリに作成されているはずなので、編集する。編集するのは以下の2箇所

extensions = ['sphinxjp.themecore']
html_theme = 's6'

make htmlする

make html

とすると、_build/html/以下にスライドができてるはず。
_static/ディレクトリにcssとかjsが入ってるんで、これも一緒にコピーしないとHTMLが半裸状態になります

CentOS5にnode.jsとsocket.ioを入れた話

node.jsのインストール方法は既にいろんなところで書かれているのだけど、何か所か詰まったのでメモ。

  • yum経由で必要なパッケージのインストール
  • node.js
  • npm
  • nvm
  • tar
  • socket.io

なお、先にnvmを入れるやり方もあって、下記のエントリが参考になる。nvm→node.js→npm→socket.ioの順でインストールすればうまくいく。
http://d.hatena.ne.jp/mollifier/20110221/p1

yum経由で必要なパッケージのインストール

$ sudo yum install openssl-devel gcc-c++

node.js

$ wget http://nodejs.org/dist/node-v0.4.11.tar.gz
$ tar zxf node-v0.4.11.tar.gz
$ cd node-v0.4.11
$ ./configure
$ make
$ sudo make install
$ node -v
v0.4.11

npm

$ sudo chown $USER /usr/local
$ curl http://npmjs.org/install.sh | sh
$ sudo chown root /usr/local
$ npm -v
1.0.27

nvm

$ npm install nvm

source ~/.bashrcしろというメッセージがでるので、その通りにすると、

$ source ~/.bashrc 
bash: /.npm/nvm/0.0.6/package/nvm.sh: そのようなファイルやディレクトリはありません

と言われた。.bashrcに上記の存在しないパスが追記されているので、
/.npm/nvm/0.0.6/package/nvm.sh を、存在するパス
.npm/nvm/0.0.6/package/nvm.sh に書き換える。

$ nvm install v0.4.8
$ nvm use v0.4.8

tar

npm経由でsocket.ioをインストールする際に、tarの1.2系が必要になるのだが、CentOS5のyumでは1.1系までしか入らないので、tarをソースからインストールする。

$ wget ftp://mirrors.kernel.org/gnu/tar/tar-1.26.tar.gz
$ tar zxf tar-1.26.tar.gz
$ cd tar-1.26
(古いtarを削除する)
$ sudo rpm -e --nodeps tar
$ ./configure
$ make
$ sudo make install

socket.io

npmで入れることができるようになる。

$ npm install socket.io

おめでてー残念登山会 in 名古屋

私が名古屋で遊べるのもあとわずかしか無いというこの時期に、モヤシとかソフトクリームデニッシュとかスイーツ系パスタ(笑)の山に登ってみようじゃないかというイベントを思いつきました!

スケジュール

12:00 名駅金時計集合

場所はわかりますよね!

コメダ珈琲エスカ店

まずはシロノワールとやらを食べます!
何個食べるかは参加者の体調次第で考えましょう!
この先どういう順路を辿るかもここで話し合って変えるのも良いと思います。


(追記)エスカ店すげー混んでるとの情報を、
匿名の名古屋市民さんからいただきました。
後述のいりなか駅にも当然のようにコメダがあるので、
そっちに行くかもしれないです。

ドニチエコキップを買いましょう!

土日は終日600円で市バス地下鉄が乗り放題のお得なきっぷです、是非ご利用ください!!

いりなか駅へ移動

東山線鶴舞線を乗り継いで、マウンテンの近くの駅まで移動します!
マウンテンまでは徒歩10分くらいです。便利な山ですよね!

マウンテン

何を頼むかは審議しましょう!

ゲーセン?

一番近いのは八事ですが、ラーメン福を諦めるなら栄とか大須でもいいかもしれません!

ラーメン福?

八事からラーメン福方面のバスが出ているので乗ると1本でいけます。
これをみんなでもりもり食べます!
http://plixi.com/p/74976758

解散

みんなを見送って解散します!
20:58名古屋発の特別快速に乗らないとうなぎシティのバスが無くなってるかも…

というわけで

宜しくお願いします!!!
個人的には名駅西口すぐの巫女居酒屋「月天」にもちょっと行きたいです…

VAIO Type PのWiMAX内蔵モデルは無線LANのドライバが違うので注意しましょう

WiMAX内蔵モデル以外はAtherosのなんとかっていうチップらしいですが、
WiMAX内蔵モデルはIntel WiMAX/Wifi Link 5150とかいうやつなので、
Intelから直接ダウンロードしましょう。

http://downloadcenter.intel.com/confirm.aspx?httpDown=http://downloadmirror.intel.com/17751/eng/ICS_Dx32.exe&agr=&ProductID=&DwnldId=17751&strOSs=&OSFullName=&lang=jpn

XP化するにあたってSonyからドライバ一式と謎のユーティリティが入ったアーカイブが落とせるけど、
そこにはAtherosのしか入っていないです。