構造式検索とは関係ないのだが、構造式の画像を作ってみる。
便利なのはURL変数としてエンコードされたsmilesを渡して、画像を出すのがいいのだろう。
URLの最大長は約2000文字。低分子化合物ならまぁー大丈夫なのかと。
大体こんなイメージ。
他方、リソースが十分なら、予めMOLからイメージを作成しておいて、ファイルシステムか
データベースのLobから取り出して表示するのもあるだろう。
まぁーここではsmilesから動的に構造式を描く方式で考えてみた
URL変数†
smilesには"="を含むものがあるので、smiles表記を16進数に変換して、それをURL変数として使ってみる。
その変換関数は、
- php5.xの場合:
echo bin2hex("c1ccccc1");
- python2.xの場合:
print 'c1ccccc1'.encode('hex')
- postgres関数の場合:
select encode('c1ccccc1'::bytea,'hex');
得られる文字はどれも「6331636363636331」となる。っで、これをURL変数として受け取ってデコードして元のsmiles表記に戻すには
- php5.4以降
hex2bin("6331636363636331");
- php5.3以前
pack("H*", "6331636363636331" );
- python2.x
print '6331636363636331'.decode('hex')
とする。
他、URL変数としては画面のサイズなどだろう。これは+とかで繋げればいいのかも知れない。
描画エンジン†
■RDKitの場合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| -
!
| import Image,ImageDraw
import cStringIO
import sys
sys.path.append('/opt/RDKit')
from rdkit.Chem import AllChem
from rdkit.Chem import Draw
def randgradient(smiles):
mol = AllChem.MolFromSmiles(smiles)
AllChem.Compute2DCoords(mol)
img = Draw.MolToImage(mol,size=(200,250))
f = cStringIO.StringIO()
img.save(f, "PNG")
print "Content-type: image/png\n"
f.seek(0)
print f.read()
if __name__ == "__main__":
if 'QUERY_STRING' in os.environ:
smiles = os.environ['QUERY_STRING'].decode('hex')
randgradient(smiles)
else:
print "Content-type: text/html\n\n"
print "non"
|
な感じで。ここでは画像サイズは固定の200x250だが、もしサイズ情報を載せるなら、splitなどで分割しておけばいいのかな。
あと、smilesを得ても変換できないときのお詫び画像を表示とかの検討が必要なのかもしれない。
っで、化合物ブラウズ画面をDHTMLX(http://dhtmlx.com/)さんのライブラリを使って表示すると
こうなる。画像サイズの調整などがあるだろうけど、タイル表示のほか、リスト表示、詳細表示もできそう。
データベースと連携して構造式を描く†
URLにデータベースに収めたキーを入れるとブラウザ上で構造式を描くには。
データベースの構築は RDKit/Cartridge、RDKit/Cartridge/DBを参照のこと。
ここでは RDKit/Cartridge/PubChem を収めたデータベースを使ってブラウザに構造式を描いてみる。
基本的には RDKit を使うのだが、python で制御するのでapacheに mod_wsgi を組み込む。これはpython#i52c8ba5を参照。
ここでは
[root@c ~]# cat /etc/httpd/conf.d/wsgi.conf
WSGIScriptAlias /depict /var/www/wsgi/depict.wsgi
[root@c ~]#
として、httpdを再起動して、構造式を描くpythonスクリプトを /var/www/wsgi/depict.wsgi に配置した
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
| import psycopg2
import sys, cgi
import cStringIO
sys.path.append('/opt/RDKit')
from rdkit.Chem import AllChem
from rdkit.Chem import Draw
def application(environ, start_response):
connector = psycopg2.connect(host="localhost", database="chemdb", user="caster", password="xxxxxxx")
cursor = connector.cursor()
query = environ.get('QUERY_STRING')
if len(query) == 0:
query = '1'
elif len(query) > 30:
query = '1'
cursor.execute("""select rdkit_smiles from pubchem where pubchem_compound_cid= %s""", [query])
result = cursor.fetchall()
for row in result:
smi = row[0]
cursor.close()
connector.close()
mol = AllChem.MolFromSmiles(smi)
AllChem.Compute2DCoords(mol)
img = Draw.MolToImage(mol,size=(200,250))
f = cStringIO.StringIO()
img.save(f, "PNG")
status = '200 OK'
f.seek(0)
output = f.read()
response_headers = [('Content-type', 'image/png'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
|
これで
と打てば、
と表示される