SMSD (Small Molecule Subgraph Detector)を使う

GastonでMCSを探索するのは色々無理があったようで、どうするかな困った困ったと探していたら、SMSDを見つけた。cdkには既に組み込まれているらしくてさっきビルドしてみたんだけど、よく考えたらCDKの使い方あんまよくわかんないや、、、ってことでGUIで遊んだ。

ちなみに、java6でビルドしないといけないので、osx(10.5)の場合は環境変数を設定した。

SMSD

とりあえず、vildagliptinsitagliptinのMCSをもとめた。

SMSD

なんで5員環と6員環がマッチしてるんだろうか?あとでペーパーちゃんと読もうっと。

追記openbabelでのdiscussもあった

Pythonで外部コマンドがPATHに存在するか探す

SWIGでgastonのPythonバインディング作るのがいいのかもしれないけど、SWIG力が足りないので、外部コマンドから使っている。

os.environ['PATH']で探してみたけど、普通はどうやるんだろうか

if 'gaston' not in reduce(lambda a,b: a+b,[os.listdir(d) for d in \
    os.environ['PATH'].split(':') if os.path.isdir(d)]):
    print "gaston: command not found"
    exit()
os.system("gaston %d %s %s > /dev/null 2>&1" % (freq,gasfile,output))

引き続き化合物のネットワークをいじっている

ノード間で類似性が最大となるような関係にひとつだけエッジを張るようにしてみた。

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

import pybel

mols = list(pybel.readfile("sdf", "pc_sample.sdf"))
fps = [x.calcfp() for x in mols] 

for i in range(len(fps)-1):
    max_sim = 0
    max_name = ""
    for j in range(i+1,len(fps)):
        sim = fps[i] | fps[j]
        if sim > max_sim: 
            max_sim = sim
            max_name = mols[j].title
    print "%s\t%s\t%s\t%2.3f" % (mols[i].title, 'sim', max_name, max_sim)

ついでに類似度属性で色が変わるようにしてみた。

network

わからん。さっきのエッジに加えて類似性が高い化合物同士のエッジは加えてみた。

for i in range(len(fps)-1):
    max_sim = 0
    max_name = ""
    targets = []
    for j in range(i+1,len(fps)):
        sim = fps[i] | fps[j]
        if sim > max_sim: 
            max_sim = sim
            max_name = mols[j].title
        if sim > 0.7:
            print "%s\t%s\t%s\t%2.3f" % (mols[i].title, 'sim', mols[j].title, sim)
    if len(targets) == 0:
        print "%s\t%s\t%s\t%2.3f" % (mols[i].title, 'sim', max_name, max_sim)

network2

ちょっとまとまりが出てきたけど、あれだなぁ。もとのsdfがそもそもあかんのかなぁ。

で、最小全域木(MST)で描くことも考えたけど化合物間の類似性の最小経路を求めてもなぁ、、、とか思ってヤル気がおきない。類似性でつないだネットワークのMSTの意義ってなんなんだろうなぁと。

なんやろかー、なんやろかー。論文もう一回ちゃんと読んでみようかなぁ。

「労働ダンピング」を読んだ

ブックオフにて。アマゾンの星の多さの割になんというか同意できない内容が多くて、そういう主張を読むという意味ではなかなか興味深かった。労働者は会社に搾取されているっていう前提で、幸せに生きる権利を獲得しなければみたいなスタンスかな。本書からは社員がなんかの目的のために集まって結果できた法人形態が会社っていう立ち位置はさらさら感じさせない。

もちろん正規、非正規にも触れていていて雇用の流動化は悪っていう主張っぽい。

ProductName 労働ダンピング―雇用の多様化の果てに (岩波新書)
中野 麻美
岩波書店 / ¥ 819 ()
在庫あり。

あと、紙切れが挟まってた。栞として便利だったのでそのまま挟んで使った。

1281613384

ということは著者は社民よりってこと?それとも共産かな、わからん。

  • 健康に有害なストレスを生み出す長時間労働や職場環境こそ改善しなければならないのだが、一定時間を超えたら産業医の指導や健康診断の実施によって労働者の健康対策を講じるというでは、労働者個々人の健康問題に収斂されてしまいかねない
  • 労働時間規制は、「何時間働けるか」ということではなく「何時間労働から開放されて時自分のための自由な時間を確保できるか」という生活の自由の確保に存在根拠があった
  • グローバル化は、本来ならば、これまでにない物質的進歩をもたらし、すべての人々に生産的で、より良い仕事を与え、貧困の撲滅に大きな貢献を擦る可能性がある
    • この主張の根拠がよくわからなかった
  • 安心して働ける仕事としてイメージされるもの
    • 働き手にふさわしい力と役割を発揮できる
    • 働き手の生活や健康、人格が大事に尊重できる
    • 自立して将来を見通しながら生きる基盤となる
  • 登録型という雇用自体この社会に認めてはならない働き方
  • 労働時間差を理由とする処遇格差が差別であるという考え方が自然に受け入れられる働き方が「ワーク・ライフバランス」というものだろう

理想はまぁその通りだと思うんだけど、それを達成しようとする手段に組合臭を強く感じた。

モチベーション3.0とかハイコンセプトが、自分で未来を切り開こう的な前向きな内容なのに対して、本書は、企業に奪われた「幸せという宝箱」を奪還しようというRPG的な内容かなぁ。まぁ、宝箱の中には「安定雇用」も「正規雇用」も入ってなくてスッカラカンだとおもうんだけどねぇ。

Gastonを使ってMCSを求める

openbabelにはMaximum Common Substructure(MCS)を求めるメソッドがないのでGastonを使った。

似たようなのは昔書いたけど扱いにくいのでクラスにしといた。ついでにMCSSTanimotoも求めるようにした。

MCSSTanimoto(A,B) =  MCS /(A + B - MCS) #全てヘテロ原子数

という、MCS版のタニモト距離。例えばOc1ccccc1 とCc1ccccc1のMCSTanimotoは

6 /(7 + 7 - 6) = 0.75

スキャフォールドが決まっている場合には割と手軽に使えんじゃないかなぁ。まぁヘテロの性質無視して同一性だけで判断しているのでハロゲンの違いは割と似ているとかそういう補正は入れたほうがいいのかもしれないが。

import openbabel as ob
import os,re
from tempfile import mkstemp

class Gaston:
    def __init__(self,mols=[]):
        self.mols = mols

    def writefile(self,filename):
        """ convert file to gaston format"""
        f = open(filename, 'w')
        for (molnum, mol) in enumerate(self.mols):
            f.write("t # %d\n" % molnum)
            for i,atom in enumerate(ob.OBMolAtomIter(mol)):
                f.write("v %d %d\n" % (i,atom.GetAtomicNum()))
            for i,bond in enumerate(ob.OBMolBondIter(mol)):
                f.write("e %d %d %d\n" % (bond.GetBeginAtomIdx()-1,bond.GetEndAtomIdx()-1,bond.GetBondOrder()))

        return filename

    def readfile(self,file):
        txt = open(file).read()
        p = re.compile('#.+?(?=(#|$))',re.S)
        mols = p.finditer(txt)

        result = [self._gas2ob(gas.group()) for gas in mols]
        return result

    def _gas2ob(self,gf):
        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 mol

    def search(self,freq=None):
        if freq == None: freq = len(self.mols)

        (m,gasfile) = mkstemp()
        (n,output) = mkstemp()
        self.writefile(gasfile)
        os.system("/opt/local/bin/gaston %d %s %s > /dev/null 2>&1" % (freq,gasfile,output))
        mols = self.readfile(output)
        os.unlink(gasfile)
        os.unlink(output)
        return mols

    def mcs(self):
        substructures = self.search()
        mcs = substructures[0]
        for substructure in substructures[1:]:
            if substructure.NumAtoms() > mcs.NumAtoms():
                mcs = substructure
            elif substructure.NumAtoms() == mcs.NumAtoms():
                if substructure.NumBonds() > mcs.NumBonds():
                    mcs = substructure
        return mcs

class MCSSTanimoto:
    def __init__(self,mol1,mol2):
        self.mol1 = mol1
        self.mol2 = mol2

    def score(self):
        mcs = Gaston(mols=[self.mol1,self.mol2]).mcs()
        return float(mcs.NumAtoms()) / (mol1.NumAtoms() + mol2.NumAtoms() - mcs.NumAtoms())


if __name__ == '__main__':
    import sys
    obc = ob.OBConversion()
    obc.SetInAndOutFormats("smi", "smi")

    mol1 = ob.OBMol()
    obc.ReadString(mol1, "CCC1=CC=CS1")
    mol2 = ob.OBMol()
    obc.ReadString(mol2, "OCC1=CC=CS1")
    mol3 = ob.OBMol()
    obc.ReadString(mol3, "CCCC1=CC=CS1")

    gaston = Gaston(mols=[mol1,mol2,mol3])
    print ":::Frequent Structures:::"
    for m in gaston.search():
        sys.stdout.write(obc.WriteString(m))
    print ":::MCS:::"
    sys.stdout.write(obc.WriteString(gaston.mcs()))
    print ":::MCSSTanimoto:::"
    score = MCSSTanimoto(mol1,mol2).score()
    print score

実行結果

:::Frequent Structures:::
CC  3
CC=C    3
C(=C)C=C    3
C(=C)C=CS   3
CC(=C)S 3
CC=CC   3
CC(=CC)S    3
CC=CC=C 3
CC(=CC=C)S  3
Cc1cccs1    3
CC=CC=CS    3
CC=CS   3
CC=CSC  3
c1ccsc1 3
CC=C(SC)C   3
CC=CSCC 3
CCS 3
CCSC    3
CC(=C)SC    3
CCSC=C  3
CC(=C)SC=C  3
C=C 3
C=CS    3
C=CSC   3
C=CSC=C 3
CS  3
CSC 3
:::MCS:::
Cc1cccs1    3
:::MCSSTanimoto:::
0.75

あと実際にモジュール化する場合にはコマンドがどこにあるかわからないし、もしかしたたらインストールされてないかもしれないけど、そういう場合にどういう感じで処理すればいいんだろうか?whichで調べるとかすんのかな?

「ハイコンセプト」を読んだ

モチベーション3.0が良かったのでこっちも読んでみたが、それほど感動はなかった。発売から5年も経ってるから内容がちょっと陳腐化したのかな?

ProductName ハイ・コンセプト「新しいこと」を考え出す人の時代
ダニエル・ピンク
三笠書房 / ¥ 1,995 ()
在庫あり。

  • 今の仕事をこのまま続けていいか
    • 他の国なら、これをもっと安くやれるだろうか
    • コンピュータなら、これをもっとうまく、早くやれるだろうか
    • 自分が提供しているものは、この豊かな時代の中でも需要があるだろうか
  • これから求められるセンス
    • デザイン
    • 物語
    • シンフォニー
    • 共感
    • 遊び心
    • 生きがい
  • 絵を描くことは関連性をみること
  • 科学は世界を理解するための方法の一つにすぎない

会社の同僚には是非読むことをススメたいとは思う。

Flaskでflotを使う

flotというjQuery製のグラフ描画ライブラリがあるのだけど、Flaskにはjsonifyがあるので連携割と楽だろうと書いてみたら超楽だった。

from flask import Flask, request, redirect, url_for, jsonify, render_template
from database import db_session
from models import Bp
from datetime import datetime
from calendar import timegm

Debug      = True
SECRET_KEY = 'development key'

app = Flask(__name__)
app.config.from_object(__name__)

@app.after_request
def after_request(response):
    db_session.remove()
    return response

@app.route('/')
def show_graphs():
    return render_template('flot.html')


@app.route('/json')
def json_bps():
    bps = db_session.query(Bp).all()
    bpp = [[timegm(bp.date.timetuple())*1000, bp.sbp] for bp in bps]
    return jsonify(bp=bpp)

if __name__ == '__main__':
    app.run()

結局どういうJSONをどのURIにマップするかを考えるのかが重要なのかな。htmlはvisitors per day with zooming and weekendsをちょっとモディファイした。

flot flask1

したのほうの小さいグラフで選択するとその領域がすぐに反映される。インタラクティブなグラフがすぐ作れる

flot flask2

recentf-extがやばい

レコ屋のポップ風だと

C-x C-fを超えた? 激モダン! ディファインキー! 萌えマスト!!

くらい?

非常に便利でもうすでに手放せない。

ちなみにC-]に割り当てた。

Emacsテクニックバイブル

すでにバリバリEmacsを使っているEmacs使いが、作業効率をカイゼンしてさらにバリバリ使うようになるための本。いきなりauto-installの導入から入って改善作業がはじまる。

特にキーバインド、検索、入力といった、対効果が高い部分のカイゼンが多めで嬉しい。 もちろんanything.elに最後の二章を割いていて、この部分はじっくり読むべきなんだけど、org-modeにもかなりのページを割いている。org-modeは使ったことないし、Sphinxのほうに興味があるので、これはそのうち使ってみようかと。

あとは、C-x v vでバージョン管理システムを使ってみる

以下気になったel

  • recentf.el
  • C-x v v
  • M-x hippie-expand
  • gist.el
  • M-!, M-|

会社の机の上のEmacs辞典と並べて置いておこう。

ProductName Emacs 辞典 (DESKTOP REFERENCE)
佐藤 竜一
翔泳社 / 3129円 ( 2006-05-11 )


「ツイッターで会社をPRする本」を読んだ

むやみやたらとフォローしまくるおはようございますしか言わんようなアカウントってどういうモチベーションで続けてるんだろう?とか、どういう本見てそういう思考になってんだろ?とか興味があって。

且つ、そういうボット的なイラッとくるアカウントをブロックする判断としてポリシー持っといたほうがいいかなとそれっぽい本を探した結果、本書を読んでみたんだけど、全然そういう本ではないどころか、かなりきちんとリサーチされていていて面白かった。

ProductName ツイッターで会社をPRする本 Twitter企業の活用例100
ひらまつ たかお
中経出版 / ¥ 1,365 ()
在庫あり。

  • フォロワーが2000人くらいになると一つのツイートで100人くらいをブログに誘導できる
  • 空気は読む必要がある
  • 目的は販売かブランド認知かはっきりさせる
  • ブランディングに合わせてフォローポリシーを変える

まぁ、ふつうのことが書いてある。