共著本と嬉しいメッセージ

先日共著本が出たのですが、知人から嬉しいメッセージが届きました。
一部ですがその中にこんなやりとりがありました。

>> あまりにも時代遅れの内容なのでこのまま内密にしておくつもりでした:-)
>> 次書くときはもうちょっとちゃんとしたものを書きたいですね。


>いやー、他のXNAの本とか見てるけど、本の内容的に買うかどうか
>を迷ったのがそもそも竹村くんの本だけだったよ。で、迷ってて、
>著者はどんな奴なんだ?ってみたら、竹村くんで、結局それ以降
>はそっちに嬉しくなっちゃって内容そっちのけで買ったのは事実
>だけど、でも、よく書けてると思うよ。

この本、そもそも私のあまりの多忙(本業+未踏+子育ての3連発)が原因で企画そのものがなくなりそうでしたが、運よく引き継いでくれる方が現れたのでこのような形で世に出ることになりました。

メッセージにもある通り、自分が納得のいくものが書けなかったので、出版したこと自体カミングアウトするつもりがなかったのですが、こんな風に本というメディアを通じて自分のことを思い出してくれる方もいるんだと知って、「あ、やっぱり世に出てよかった」と思う今日この頃です。そして共著者のxelfさんに感謝。

本の内容についてはこちら

Maximaで球面調和関数展開

Maximaという数式処理ソフトを知っていますか?これ、フリーながらかなりの高機能で、個人的にかなり重宝しています。そんなMaximaの威力を、CG屋さんに馴染み深い例で紹介しましょう。SH(Spherical Harmonics)の関数展開です。

それではまずMaximaを立ち上げて、ためしにY(l=3,m=3)を求めてみましょう。
SHの場合、プリセットで定義されているので、

INPUT:spherical_harmonic(3,3,theta,phi);

と入力するだけで

$$\frac{5\,\sqrt{7}\,{e}^{3\,i\,\phi}\,{sin\left( \theta) }^{3}}{8\,\sqrt{5}\,\sqrt{\pi }}$$

と出てきます。複素数がそのまま出てきてしまっているので、ここでは実数(m<0なら虚数)を抽出しておきましょう。ついでにsqrt(2)もかけておきます。

INPUT:realpart(%) * sqrt(2);
$$\frac{5\,\sqrt{2}\,\sqrt{7}\,cos\left( 3\,\phi) \,{sin\left( \theta) }^{3}}{8\,\sqrt{5}\,\sqrt{\pi }}$$

でました。これだけでも十分に実用的な計算式なのですが、極座標系から直交座標系への変換にも挑戦してみましょう。Maximaではまず以下のおまじないが必要です。

INPUT:%,trigexpand=true;
$$\frac{5\,\sqrt{2}\,\sqrt{7}\,\left( {cos\left( \phi) }^{3}-3\,cos\left( \phi) \,{sin\left( \phi) }^{2}) \,{sin\left( \theta) }^{3}}{8\,\sqrt{5}\,\sqrt{\pi }}$$

これは三角関数の展開を意味しているのですが、Maximaではこの手続きを踏まないと以下の変換が何故かうまくいきませんでした。唯一のハマりポイントと言えるでしょう。それではtheta,piの順に関数合成します。

INPUT:ratsubst(acos(z),theta,%);
$$-\frac{\left( 15\,\sqrt{2}\,\sqrt{7}\,cos\left( \phi) \,{sin\left( \phi) }^{2}-5\,\sqrt{2}\,\sqrt{7}\,{cos\left( \phi) }^{3}) \,{\left( 1-{z}^{2}) }^{\frac{3}{2}}}{8\,\sqrt{5}\,\sqrt{\pi }}$$
INPUT:ratsubst(atan2(y,x),phi,%);
$$-\frac{\left( 15\,\sqrt{2}\,\sqrt{7}\,x\,{y}^{2}-5\,\sqrt{2}\,\sqrt{7}\,{x}^{3}) \,{\left( 1-{z}^{2}) }^{\frac{3}{2}}}{8\,\sqrt{5}\,\sqrt{\pi }\,{\left( {y}^{2}+{x}^{2}) }^{\frac{3}{2}}}$$

x^2+y^2が冗長なのでこれを消去してしまいます。

INPUT:ratsubst(x^2+y^2,1-z^2,%);
$$-\frac{15\,\sqrt{2}\,\sqrt{7}\,x\,{y}^{2}-5\,\sqrt{2}\,\sqrt{7}\,{x}^{3}}{8\,\sqrt{5}\,\sqrt{\pi }}$$

はい、できあがりです。欲を言えば分母のルートを消したいところですが、やり方がわかりませんでした。またl,mの値によってはこれでも冗長な結果が出ることもあります。その場合は、

INPUT:ratsimp(%);

を実行してください。また実際に畳み込みに使うときは正規化項を忘れずに入れてくださいね。

ところでStupid SH Tricksによると、かのPeter-Pike SloanはMapleを愛用されているそうです。でもこの位ならMaximaでも十分いけますよ、という例でした。

天下一を超えられるのは天下一しかない。前人未到のプレゼン大会レポート

というわけで、第弐回天下一カウボーイ大会に参加して参りました。前回も約1名を除いて凄い講演者が集いましたが、今回は”もう世界で清水さん以外に出来ないだろ”っていう位のイベントになってしまいました。講演内容は、yoshifujiさんのcode雑記帳にてとても良くまとめられています。復習用にどうぞ。個人的にはこのプレゼンだけでも8000円以上の価値があったと思います。


そしてAlty Partyも前回以上の飛ばしっぷり。しかしこんな1幕もありました。終盤、会場の方と談笑していたら、


「教授!」
「教授!」


「西○教授!」


と心配そうな声が会場から連呼するではありませんか。


「あまりのヒートアップぶりに誰かぶっ倒れてしまったのか!!!!」



と壇上を見上げたら、そこには麗しきカウガール達と嬉しそうに緊縛プレイに興じるCoons賞のお姿が。。。はい、偉い人も皆揃ってどうかしちゃうくらい、会場は盛り上がっていたみたいです。

最後に清水さんに「次は(Appleの)増井さんでお願いしますよ」と無茶な要望を出しながらの感謝の挨拶。もう「天下一を超えられるものは天下一しかない」、と誰もがそう感じながら会場を後にしたのではないかと思います。1年後が楽しみでなりません。

最後に例のサプライズなプレゼントは、、、行けなかった同僚にプレゼントしたいと思います。

東京を生かしきれてない自分

ソーシャルブックマーク研究会という、貴重な学びの機会があったことに今更気づいた。

うーんなんたることだ。毎日チェックするGoogle Readerには技術系ブログが100個以上、IT勉強会カレンダーやGoogle Groupを定期的にチェックするなど、情報収集は怠りなくやってきたつもりなのに。一瞬で埋まったAppEngineイベントの奪取に成功して、これで都会人の仲間入りかと思っていた矢先にこれだ。東京というチャンスの塊のような町をまるで活用できてない。

というわけで今はスライドを見て、その内容の充実ぶりに打ちのめされているところ。うーん、これ、そこらへんの人工なんたら学会シンポジウムより全然旬な内容だわ。

でもこうも思う。これくらいのイベント、テキストマイニングで発見できなきゃダメだよねと。SNS、blog、チャット、あらゆる情報発信媒体から、書き手の関心を機械的に分析し、それを他者の関心とマッチングさせることで重要度の高いイベントを自動的に見つけ、登録する学習型カレンダー。これくらいのことが当たり前に出来てやっとWeb2.0ないんじゃないかと。

時代は確実に集合知プログラミングの世界に向かっている。RやPythonの良書も増えてきた。でもまだまだこれから。自分もこの未熟なインターネットを少しでも良くするべく闘っていこうと思う。

pythonでYahoo BOSS APIを使うサンプルコード

Yahoo BOSS APIを使ったpythonのサンプルプログラムです。実はHTTPリクエストで長らく失敗していたのですが、'Accept-encoding'を設定することで、解決できました。この件についてはHatena::Questionやmixiなどを通じ、沢山のアドバイスを頂きました。本当に感謝しております。

ソースコードは以下の通りです。こちらは、公式のBOSS Frameworkよりもずっとシンプルなのが特徴です。

#!/virtual/taos/bin/python
#!-*- coding:utf-8 -*-

import sys
import site

import os
import re
import codecs
import cgi;
import cgitb; cgitb.enable()
import logging
import datetime
from urllib import urlencode
from urllib import quote_plus
import urllib2
import simplejson

#BOSSのAppIDはconfig.json内に忍ばせてます(BOSS Framework参照)
CONFIG = simplejson.load(open("config.json", "r"))
SEARCH_API_URL = CONFIG["uri"] + "%s/v%d/%s?start=%d&count=%d&lang=%s&region=%s" + "&appid=" + CONFIG["appid"]

def download(url):
	try:
		req = urllib2.Request(url)
		#この'Accept-encoding'の設定が絶対必要!!!
		req.add_header('Accept-encoding', 'gzip')
		r = urllib2.urlopen(req).read()
		return r
	except urllib2.URLError, error:
		return " (%s %s)" % (error.code, error.msg)

def params(d):
  """ Takes a dictionary of key, value pairs and generates a cgi parameter/argument string """
  p = ""
  for k, v in d.iteritems():
    p += "&%s=%s" % (quote_plus(k), quote_plus(v))
  return p

def search(command, vertical="web", version=1, start=0, count=10, lang="en", region="us", more={}):
  """
  command is the query (not escaped)
  vertical can be web, news, spelling, images
  lang/region default to en/us - take a look at the the
  YDN Boss documentation for the supported lang/region values
  """
  url = (SEARCH_API_URL % (vertical, version, quote_plus(command), start, count, lang, region)) + params(more)
  return download(url)
  #return simplejson.loads(download(url))


#sys.setdefaultencoding('UTF-8')
sys.stdout.write('Content-type: text/html; charset=UTF-8\n')
sys.stdout.write('Cache-Control: no-cache\n')
sys.stdout.write('\r\n\r\n')

sys.stdout.write("""
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="javascript">
<title>"Positive Search</title>
</head>

<body>""")

results=search("はてな","web",1,0,10,"jp","jp")

search_results = None
totalhits = 0
if results.has_key('ysearchresponse'):
	if results['ysearchresponse'].has_key('resultset_web'):
		search_results = results['ysearchresponse']['resultset_web']
	if results['ysearchresponse'].has_key('totalhits'):
		totalhits = results['ysearchresponse']['totalhits']

for res in search_results:
	sys.stdout.write(unicode(res['title']).encode('utf-8'))
	sys.stdout.write("<br>")

sys.stdout.write(str(totalhits))

sys.stdout.write("""
</body>

</html>""")

mod_pythonを使ってデバッグする場合

ローカル環境でMySQLdbなどが必要な場合はこちら。
xreaではmod_pythonは使えません。同一コードで双方通す場合は、sys.platform分岐が使えるかも(要検証
コードはこんな感じ

from mod_python import apache

def handler(req):
   req.content_type = ‘text/html'
  req.write(”""...""”)
  return apache.OK

mod_pythonWindowsにインストールする方法(参考に)
http://hidekiitakura.com/blog/?p=110

SQL Connectivity With Python (参考に)
http://www.devshed.com/c/a/Python/MySQL-Connectivity-With-Python/

CGIHTTPServer使ってデバッグする場合

コード無修正のままxrea上で実行可能。ただしMySQLdbとかは使えない。

.projectのあるフォルダに以下の内容のRun.pyを作っておいてRun DialogのMain Moduleに"${workspace_loc:project_name}/Run.py"と登録しておくとよい(なお、srcフォルダはcgi-binにリネームすること)

import os, BaseHTTPServer, CGIHTTPServer,SimpleHTTPServer
class PyHTTPRequestHandler(CGIHTTPServer.CGIHTTPRequestHandler):
    def do_POST(self):
        if self.is_cgi():
            CGIHTTPServer.CGIHTTPRequestHandler.do_POST(self)
        else:
            self.do_GET();
    def is_python(self,path):
        head,tail=os.path.splitext(path)
        return tail.lower() in (".py", ".pyw",".cgi") #warning!
os.chdir(os.path.abspath(os.path.dirname(os.path.realpath(__file__))))
CGIHTTPServer.CGIHTTPRequestHandler.cgi_directories = ['/cgi-bin']
BaseHTTPServer.HTTPServer(
    ('127.0.0.1', 8080),
    PyHTTPRequestHandler
    ).serve_forever() 

この場合窓口URLは以下の通り
http://localhost:8080/cgi-bin/index.py
コードはこんな感じ

!/virtual/taos/bin/python
#!-*- coding:utf-8 -*-
 
import sys
import site
import os
import re
import codecs
import cgi;
import cgitb; cgitb.enable()
import logging
import datetime
 
sys.stdout.write('Content-type: text/html; charset=UTF-8')
sys.stdout.write('\r\n\r\n')
sys.stdout.write("""
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
....
</html>""")