pubchemスクレイピング

mixiでpubchemからSMILESを抜き出すのは?みたいなエントリがたってたのだけど消えちゃったみたい。

なんか、ここは宿題まるなげちゃうわーみたいな厳しいコメントついてたからかな。まぁああいったコメント書くヒトはすっきりするのかもしれんけど、見るほうにとっては情報量ゼロのゴミなんだよなー。まだ、課題まるなげっていう情報のほうが情報量的に有意義。

ちょっと考えたのでここに書いておく。

XMLをBeautifulSoupで

import urllib2,sys
from BeautifulSoup import BeautifulSoup

cid = sys.argv[1]
url = 'http://pubchem.ncbi.nlm.nih.gov/summary/summary.cgi?cid=%s&disopt=DisplayXML' % cid

opener = urllib2.build_opener()
html = opener.open(url).read()
soup = BeautifulSoup(html)

print soup.findAll('pc-infodata_value_sval')[-2].string 

xmlがなんかfindしにくいので配列の要素指定に-2とかやって良くない香り。この程度のだったらxmlじゃなくてSDFを正規表現でいじるな。

import urllib2,sys,re

cid = sys.argv[1]
url = 'http://pubchem.ncbi.nlm.nih.gov/summary/summary.cgi?cid=%s&disopt=DisplaySDF' % cid

html = urllib2.build_opener().open(url).read()
p = re.compile('<PUBCHEM_OPENEYE_CAN_SMILES>\n(.+)\n')
m = p.search(html)
print  m.group(1)

biopythonとかでもいけそうな気がするし、urllib2+openbabelの組み合わせでも良いかもしれない。

Project Euler Problem 41

1からnまでの連続した数をおのおの一つだけ桁にもつ素数のうち最大のものを探せ

987654321から数を減らしながら素直に見つけていくという安直なコードを書いてサブミット。

import math

def make_primes(n):
    primes = [2]
    nums = range(3,n+1,2)
    while 1:
        prime = nums[0]
        if prime ** 2 > n:
            primes += nums
            return primes
        else:
            primes.append(prime)
            nums = [x for x in nums if x%prime != 0]
    return list(set(primes))

def permute(item):
    if len(item) == 1: yield item
    for i in range(len(item)):
        for x in  permute(item[:i]+item[i+1:]):
            yield item[i] + x

def is_prime(n):
    for j in primes:
        if j*j > n: return True
        if n%j == 0: return False
    return True

if __name__ == "__main__":
    num = 7654321
    primes = make_primes(int(math.sqrt(num)))

    for i in permute(str(num)):
        x = int(i)
        if x%2 != 0:
            if is_prime(x):
                print x
                break

それよりもみずぴー日記のコメントが参考になった。

「各桁の数を足した和が3の倍数ならその数自身も3の倍数」って性質から、素数のPanditital数はあるとすれば1桁か4桁か7桁に絞られるんじゃないでしょうか。

えーなんでなんでー????

3の倍数のANo3をみてなるほどなーと感心した。

オープンソースで始めるゲノム・プロテオーム・メタボローム解析

perl,python,Rでオームな解析をするための本。ツールやデータベースの説明が主なので、ハウツーな感じではなくて、インフォマティクス側からみたバイオロジーとかケミストリーのサービスとかツールのレビューに近い感じかも。

個人的には5章のケモインフォのとこと、9章のRの章が面白かった。

codereposのコミット権をいただいた

codereposのコミット権をいただいたので早速設定した

emacsのあたりで。

それから来年はちょっとまじめにprocessingをやりたいところなので/lang/processingになにかコミットできたらいいなぁと。

GASTONの出力ファイルをsmilesに変換する

SDFからGASTON実行できるようにしたので、結果を解釈するためにsmilesに変換するコードを用意した。

import re
import openbabel as ob

def convert(gf):
    obc = ob.OBConversion()
    obc.SetOutFormat('smi')
    mol = ob.OBMol()

    for l in gf.split('\n'):
        if len(l) > 0 and l[0] == 'v':
            a = mol.NewAtom()
            atomic_num = int(l.split(' ')[2])
            a.SetAtomicNum(atomic_num)

        elif len(l) > 0 and l[0] == 'e':
            begin_atom_idx = int(l.split(' ')[1]) + 1
            end_atom_idx   = int(l.split(' ')[2]) + 1
            bond_order     = int(l.split(' ')[3])
            b = mol.AddBond(begin_atom_idx, end_atom_idx, bond_order)

        elif len(l) > 0 and l[0] == '#':
            title = l.split(' ')[1]
            mol.SetTitle(title)

    return obc.WriteString(mol)

if __name__ == '__main__':
    txt = open('gaston.out').read()
    p = re.compile('#.+?(?=(#|$))',re.S)
    m = p.finditer(txt)

    for ss in m:
        print convert(ss.group())[:-1]

実行結果

NC  11
NCC 11
NCCC    11
NCC(=C)C    11
NCCC=C  11
NCC(=C)C=C  11
NCCC=CC 11
NCC(=C)C=CC 11
NCC=C   11

頻度の高いフラグメントのSMILESと、その分子のIDが出力される


それにしてもpythonの正規表現はややこしいなぁと、みんなのpythonを読み返して復習

ProductName みんなのPython
柴田 淳
ソフトバンククリエイティブ / ¥ 2,940 ()


正規表現文字列 -> コンパイル -> 正規表現オブジェクト -> マッチ処理 -> マッチオブジェクト

SDFからGASTON用のファイルを作る

gSpanGASTONの入力はラベル付きのvertexとedgeなので、openbabelでsdfを読み込んで、GASTONのinputに変換するものを作ってみた。

import openbabel as ob

def convert(sdf):
    obc = ob.OBConversion()
    obc.SetInAndOutFormats('sdf','smi')

    mol = ob.OBMol()
    next = obc.ReadFile(mol,sdf)
    molnum = 0
    while next:
        # mol
        print "t # %d" % molnum
        # atom
        for i,atom in enumerate(ob.OBMolAtomIter(mol)): 
            print "v %d %d " % (i,atom.GetAtomicNum())

        # bond
        for i,bond in enumerate(ob.OBMolBondIter(mol)): 
            print "e %d %d %d" % (bond.GetBeginAtomIdx()-1,bond.GetEndAtomIdx()-1,bond.GetBondOrder())

        mol = ob.OBMol()
        next = obc.Read(mol)

        molnum += 1
    return True

if __name__ == "__main__":
    sdffile = 'pubchem_sample.sdf'

    convert(sdffile)

SDFはpubchemから適当に選んだがCID: 16757835は外しといた。

./gaston 11 pubchem_data pubchem_out

GASTONを実行した出力の一部

# 14
t 163
v 0 6
v 1 6
v 2 1
e 0 1 2
e 1 2 1
# 12
t 164
v 0 6
v 1 6
v 2 1
v 3 1
e 0 1 2
e 0 3 1
e 1 2 1

アロマティックなボンドは3みたいに別のラベルを与える必要がある気はするが、、、

後は、GASTONの出力ファイルから構造を構築するものを用意すれば、頻出する部分構造を扱えるようになる。

Inline::Python

Inline::Pythonのバージョンがあがったのでmacbookに入れて遊んでみた。

generatorが使いたかったのだけど、nextを呼ぼうとすると

Can't call method "next" without a package or object reference at test.pl line 3.

と怒られてしまうのであった。

HTSは高階関数

今度の発表の掴みを考えてみた。

htsはアッセイという関数を引数にとりコンパウンドリストを返す高階関数と考えることができる。

def hts(assay,library):
    criteria = 50 # %inh
    return [c for c in library if assay(c) > criteria]

うーん、マニアすぎるか

def chemist(comp):
    return modify_compound(c)

これまたあれだな。

chemoinformatics (python)

おー、このタイムライン分かりやすい。

インフラとしてはディスクリプターをどう発生させとくか(毎度毎度モデル構築のたびに発生させるのはだるいし、基本的に一回作っとけば良いのでコンパウンドをどっかに登録するタイミングでバックグラウンドでやればいい仕事)とデータへのアクセス方法(いまはRESTっぽいのがいいんじゃないかと思ってる)をきちんとやっておけば、僕らはモデル構築の試行錯誤にそのリソースのほとんどを投入できていいよね。

ProductName RESTful Webサービス
Leonard Richardson,Sam Ruby
オライリー・ジャパン / ¥ 3,990 ()
在庫あり。

あと、こういう状況だと、モデル構築能力的には常に最先端のアプローチを試せるような状況にしとかないとまずいから、自然とデフォルトの環境がRになるような気がするし、立ち位置もデータマイニング寄りになると思うんだよね。

そして、立ち位置がマイニング寄りになっちゃうと、ケモインフォマティクスとかバイオインフォマティクスってのは、新しいモデル化の方法を試すための一つのターゲットに過ぎなくて、プロジェクトのモデル化とか創薬ビジネスモデル構築とかのほうに興味が移っちゃうのだよなぁ。

関西のpythonの集まり

僕は最近プログラミングのセミナーよくいくんですよねー(楽しいし)的な話をしていて、pythonも関西のほうで時々集まりがあるらしいですよ。とか話したんだけど、どこでみかけたのか思い出せなかった。

僕も職場ではpython比率が高まっているのだけど、最近はpythonでさくさく書けるようになってきたので、そろそろgaucheあたりに移行しようかと。

openbabelのバインディングでも書いてみたい。そして、schemeでchemoinformaticsとか言ってみたい気もする。というか、なんかのSARモデルを構築したと仮定して、そのモデルを満たすような化合物をヒューリスティックに探索するとかいう場合に継続を使うと面白そうな気がするのだ。