gWTで何をやりたいのかっていう発表をしてきた。

今週、来週と発表が続いでいるのだけど、今日は(自分の中で)アツいgWTを製薬コミュニティの中で紹介してきて、そういう手法を使って何をやりたいのかっていう話をしてきたが有意義なレスポンスをいただけて非常に良かった。特にアルゴリズム系に興味あるヒトと繋がれたのと、同じような仕事のやり方をしている人とも話が出来たので、ユーザー会に出た価値があったかなと。

というより、初めて挨拶させていただいた複数の方から「ブログ見てるで」ということを言われて話を合わせやすかったので、ブログいいよなと再認識した。

それから、WizePairZの論文のAuthorにおもろかったでと言われたのだけど、そのときは著者だと認識できてなくて後からその方が発表中にAuthorだと気づいて、「おー!論文いつも楽しく読んでますよー」と念をとばしてみた(が当方変化型なので放出レベルは低いかも)。ちなみに来週はMMP絡みの話をするというか、activity cliffをプロジェクトのインシデントしてダブラズモラサズMECE精神で機械に自動的に拾わせるという話をするのだけど、また有意義な議論が出来ればいいなぁと。

python-pptxで表をつくってみた

python-pptxがテーブル対応していたので早速使ってみた。これはヤヴァイ、スクリプトで自動化したら快適になりそうな予感がする。

が、いまのとこ6行以上を指定するとファイルが出力できない模様。

test_table

from pptx import Presentation
from pptx.util import Inches
from pychembldb import *

prs = Presentation()
title_only_slidelayout = prs.slidelayouts[5]
slide = prs.slides.add_slide(title_only_slidelayout)
shapes = slide.shapes

shapes.title.text = "10.1016/S0960-894X(01)80693-4"

rows = 6
cols = 6
left = Inches(0.5)
top = Inches(1.5)
width = Inches(8.0)
height = Inches(0.8)

tbl = shapes.add_table(rows, cols, left, top, width, height)

tbl.columns[0].width = Inches(2.0)

tbl.cell(0, 0).text = 'inchi_key'
tbl.cell(0, 1).text = 'activity'
tbl.cell(0, 2).text = 'HBD'
tbl.cell(0, 3).text = 'HBA'
tbl.cell(0, 4).text = 'PSA'
tbl.cell(0, 5).text = 'MWT'

for journal in chembldb.query(Doc).filter_by(doi="10.1016/S0960-894X(01)80693-4"):
    for assay in journal.assays[:1]:
        for i, activity in enumerate(assay.activities[:5], 1):
            tbl.cell(i, 0).text = activity.compound.molecule.structure.standard_inchi_key
            tbl.cell(i, 1).text = str(activity.published_value)
            tbl.cell(i, 2).text = str(activity.compound.molecule.property.hbd)
            tbl.cell(i, 3).text = str(activity.compound.molecule.property.hba)
            tbl.cell(i, 4).text = str(activity.compound.molecule.property.psa)
            tbl.cell(i, 5).text = str(activity.compound.molecule.property.mw_freebase)

prs.save('test.pptx')

追記 130605

というわけでSHizuoka.py #2も楽しいよと、ちょいと宣伝しておきます。

chembl_15をサポートしてバージョンもあげた(pychembldb)

先週バージョンが上がってスキーマもかなり変更されたchembl_15に対応させました。

ChEMBLはバージョンアップでおもに結合サイトまわりが強化されているみたいです。binding_siteとかpredicted_binding_domainみたいなデータが入っているのはドッキングシミュレーションを強く意識した作りになっているんでしょう。とはいえ、いい感じのOSSなドッキングシミュレーションソフトウェアがないから、遊びにくいかも。

スキーマに関して言えば、多対多はすっきりとした感じに変更されてたのでmapper書きやすくなっててよかったが、ちょいとハマったところをメモっておく

  • target_dictionaryとpredicted_binding_domainsがone-to-manyになってなくてactivityに紐付いてる
  • information_source doesn't exist in products table
  • USAN_STEMがautoでマップできないのでとりあえずコメントしてある

あとはテストケース書くのがめんどくさかったので自動生成するようにした。今回はクラスもある程度自動生成した(utils)。

doctest書かないといけないなぁと思った。

ChEMBLデータベースのPythonインターフェースを書いた

ちょっと欲しくなったので探してみたらpychemblを見つけた。

しかしメンテされてないようなのでフォークして更新しようかなと思い、ソースを眺めたら面倒くさそうな感じだったので、昨日一日使って新しいのを作ってみた。

declarativeでautoloadしているのでスキーマが変わってもメンテしやすいかなと思う。コーディングのほとんどの時間をテスト書くのに使ったので結構疲れた。それから、メタプログラミングはどうかなと思ったのでdbのuriは環境変数CHEMBL_URIで設定するようにしておいた(デフォルトはchemblのmysqlのインストールそのまま)。

chembl = ChEMBLDB(uri)とかやりたい場合にはFlask-SQLAlchemyのソースが参考になると思う。

ターゲットから活性値とInChiKeyをフェッチする

ターゲット名に含まれるアッセイ系から活性と対応する化合物の構造をとってくる。

from pychembldb import *
for target in chembldb.query(Target).filter_by(pref_name="Tyrosine-protein kinase ABL"):
    for assay in target.assays:
        for activity in assay.activities:
            print activity.published_value, activity.molecule.structure.standard_inchi_key

ジャーナルから活性値とInChiKeyをフェッチする

ジャーナル(doi)に含まれるアッセイ系から活性と対応する化合物の構造をとってくる。

from pychembldb import *
for journal in chembldb.query(Doc).filter_by(doi="10.1016/S0960-894X(01)80693-4"):
    for assay in journal.assays:
        for activity in assay.activities:
            print activity.published_value, activity.molecule.structure.standard_inchi_key

その他

ChEMBLのスキーマみれば大体わかるだろうし、その通りに動くでしょう。このスライドも参考になると思う。

余談ですが、Rubyだとbio-chemblがあるそうです。

今後やる予定のこと

  • とりあえずテーブル名をそのままクラス名にしたせいでlookupとかDictionaryとかついててダサいのでそこら辺の名前は変える(なのでクラス名とかメソッド名はまだ変わります)
  • relationが不完全なので追加していく
  • one-to-oneみたいなのもone-to-manyとしてrelation張っているせいでリストになっている部分は修正する(上だとmolecule.structures[0]とかださい)
  • pypiに登録する(pipでインストール出来ないと面倒くさい)

130128 追記

  • one-to-oneにしたのでmolecules[0]がmolecule
  • Dictionaryを除いたのでTarget,Moleculeになった

化合物の入力にjava製のプラグインはもう流行んないだろうなぁと思った

NARのDatabase IssueにMMPのサービスが載るんだとか思いつつ、SwissBioisostereにアクセスしたら、構造描画にjava製のプラグインを要求するので使うのをやめた。

なんかが良いかなと思うが。chemdoodleのチュートリアルは結構面白いしbackbone.jsなんかと組み合わせられるんじゃないかなぁ。

あとで試す。

Graph-indexing wavelet tree (gWT)のグラフ検索が超速い

高速文字列解析の流れで、タイミングよく統数研チャンネルの資料が公開されていて、最後のほうのスライド(65枚目)にグラフの類似度検索の実装としてgwtが紹介されていたので遊んでみた。

データベースは、ChEMBLから取ってきた。なぜpubchemじゃないかというと面倒なので略。

入力のフォーマットがgSpanとかGASTONと一緒だったので、昔書いたのを流用しようとしたんだが、昔書いたpythonスクリプトはどうもOBMolAtomIterあたりがバグっていて動かないようだ(OBMolBondIterも動かなかった。)

File "sdf2gsp", line 17, in convert
  for i,atom in enumerate(ob.OBMolAtomIter(mol)): 
File "/usr/local/Cellar/python/2.7.3/lib/python2.7/site-packages/openbabel.py", line 4499, in __init__
  if not self.iter.__bool__():
AttributeError: '_OBMolAtomIter' object has no attribute '__bool__'

しょうがないのでiterateしない版で書き換えた。

#!/usr/bin/env python
import sys
import pybel
import openbabel as ob

def convert(sdf):
    mols = pybel.readfile('sdf',sdf)
    for n, mol in enumerate(mols, 1):
        print "t # %d" % n
        for i in range(mol.OBMol.NumAtoms()):
            print "v %d %d " % (i+1, mol.OBMol.GetAtom(i+1).GetAtomicNum())
        for j in range(mol.OBMol.NumBonds()):
            b = mol.OBMol.GetBond(j)
            print "e %d %d %d" % (b.GetBeginAtomIdx(),
                                  b.GetEndAtomIdx(),
                                  b.GetBondOrder())

if __name__ == "__main__":
    sdffile = sys.argv[1]
    convert(sdffile)

ちなみにこの形式に名前ついているんだろうか?babelとかでサポートされないと使い勝手が悪いんだけどなぁ。

これで、ChEMBLの137万件をgspにコンバートしてみたけど遅すぎるので後でHaskellで書きなおす。sdf単に舐めるだけだからOBMolに変換する必要もないし。

できたchembl_14.gspからindexファイルをつくる。600M(137万化合物)で10分ぐらいかかった@MBA。

./gwt-build -iteration 2 chembl_14.gsp chembl14

検索はみんな大好きImatinibをgspにしたものを使った。

$ ./gwt-search -kthreshold 0.8 chembl14 query.gsp
reading index file:chembl14
end reading
start building rank dictionary
end building rank dictionary
start transferring labels
end transferring labels
id:0 1080597:0.809449 712949:0.838758 413038:0.847826 \
394513:0.826087 391369:0.819028 179393:0.815124 \
175534:0.899647 48523:0.804348 47164:1.000000 16405:0.802727 
cpu time (sec):0.712119
mean cpu time (sec):0.712119

と5,6秒程度で計算終了。ウリィィィィって言いたくなるほど圧倒的に速い。

bayonも感激したけど、それ以上にgwtはすごいなぁと思った。

OS10.8.2にopenbabel2.3.2をインストール

2.3.1のままだったので、昔のログを見ながらインストール。

が、古いswig(/usr/binにあるやつ)を見ていてエラーになるので、SWIGの場所をcmakeに知らせたいのだがオプションがわからない。

調べたトコロ

cmake -L

で一覧が出るらしい。必要なのはSWIG_EXECUTABLEなので

cmake ../openbabel-2.3.1 -DPYTHON_BINDINGS=ON \
-DPYTHON_LIBRARY=/usr/local/lib/libpython2.7.dylib\
-DPYTHON_EXECUTABLE=/usr/local/bin/python \
-DEIGEN2_INCLUDE_DIR=/Users/kzfm/openbabel/eigen-eigen-2.0.17 \
-DRUN_SWIG=ON \
-DSWIG_EXECUTABLE=/usr/loca/bin/swig

でOK

Bioisosteres in Medicinal Chemistry

見逃してた。これは超欲しい。

opensourceでRXNかSMIRKSのあつかえるchemoinformaticsのライブラリが欲しいなぁ。

高速文字列解析の世界を読み始めた

僕のフィールドには一応Bioinformatics,Chemoinformaticsも含まれているので、文字列だけでどこまでいけるのかは非常に興味がある。まぁ物理法則を無視できなくなってくると文字列処理ではどうしようもないんだけどね。

3章のBWTまで読んだけど、3-4のBWTの性質と復元のところがさらっと流されていてさっぱり分からなかったので、検索したらわかりやすい説明を見つけた。

が、全体的には丁寧に解説されていて、分かりやすいと思うし、読んでて楽しい。

個人的にはSMILESみたいな構造情報を文字列にしたものをBWTで扱えないかなぁと考えている(chemoinformaticsに応用してみたい)。構造変換ルールにもイディオムみたいなのあるしね。MMPを高速に検索できても嬉しいだろうし、なんか使い道がありそうな気がするんだけど。

ChEMBLのデータにアクセスしたくなったらSQLAlchemyを使うとよい

ローカルに構築したChEMBLにアクセスする場合には生のSQLじゃなくてSQLALchemyを使ったほうが楽だ。その場合にはMetaDataのrelflectをTrueで。

from sqlalchemy import create_engine, MetaData

db = create_engine('mysql://user:password@localhost/chembl_14?charset=utf8&use_unicode=0')
metadata = MetaData(bind=db, reflect=True)

table = metadata.tables['target_dictionary']
stmt = table.select(table.c['organism'] == 'Homo sapiens')

for r in stmt.execute():
    print r.chembl_id, r.pref_name

ChEMBLって、生物種を正規化してないのね。パフォーマンスの問題かな?

ProductName Bioinformatics Programming Using Python
Mitchell L. Model
Oreilly & Associates Inc / 5075円 ( 2009-12-23 )