CDKで型があわねーとかいうエラー

Depth-FirstでみっけたStructure-CDKが使いたいということでcdk-20050826.jarからcdk-20060714.jarにあげたらこの前つくったモジュールが動かなくなった。

sdg.setMolecule(mol);
sdg.generateCoordinates();
mol = sdg.getMolecule();

のところで、

Smi2Mol_899b.java:49: 互換性のない型
検出値  : org.openscience.cdk.interfaces.IMolecule
期待値  : org.openscience.cdk.Molecule
        mol = sdg.getMolecule();
                             ^
エラー 1 

もげー、型が違うってなんでじゃ?

CDK使ったモジュールを書いてみた

Inline::JavaでCDKのニ次元構造立ち上げをperlでやれるようになったんだけど、やっぱuseして使いたいのでモジュール化してみた。

最初、Inlineでモジュールを書く方法の通りに書いてみたらエラーを吐いて動かないので、どうしたもんかと。
で、少し探してみたら、あまり深く考えなくて、普通にコンストラクタだけ用意してやればOKということらしい。

use 5.008008;
use strict;
use warnings;

our $VERSION = '0.01';

use Inline Java => "DATA";

sub new {
    my $class    = shift;
    return CDK::Simple::smi2mol->new();
}

1;

__DATA__
__Java__
import java.io.StringWriter;
import java.io.IOException;
後はjavaコードがジャヴァジャヴァと。

で、使ってみる。

my $parser = CDK::Simple->new;    
my $smiles_string = "C(=O)O";
print $parser->convert($smiles_string);

お~、モジュールだ。実行すると無駄にタメがあるのはjavaだから~。ところで、newでblessする必要はないのかな?とか気になる。

実際に作ってみて、Inline::Java使ったモジュールは意外に簡単だった。

Inline::JavaでCDKのニ次元構造立ち上げをperlから

_in house_でケモインフォ関連のプログラミングをするのに、二次元構造の立ち上げツール(またはライブラリ)と、構造描画ツールは必須だが、いまのとこCDKを使うという選択肢しかない。

実用PerlプログラミングにInline::Javaを使うとjavaのコードをperlに組み込めると書いてあったので、CDKを組み込んでみたヨ。

ProductName 実用 Perlプログラミング 第2版
Simon Cozens
オライリージャパン / 3360円 ( 2006-03-01 )


まぁ、要するに、
Q.そこまでしてperlで処理したいのか?
A. もちろんですヨ、奥さん
ということなんだが。

さて、インストールはj2sdkの場所を指定しないといけないのでcpan -iだとこける。そのため地道に、buildディレクトリで再インストール。

$ cd .cpan/build/Inline-Java-0.51
$ perl Makefile.PL J2SDK=/usr/java/jdk1.5.0_08/
$ make java
$ make
$ make test
$ make install

ただ、make javaで

:入力ファイルの操作のうち、未チェックまたは安全ではないものがあります。
注:詳細については、-Xlint:unchecked オプションを指定して再コンパイルしてください。

とかいう警告が出るが、testは通るのでまぁ気にしないということで。

で、コードを書いてみる。

参考にしたjavaのコード

:::java use Inline Java => <<'END_OF_JAVA_CODE' ; import java.io.StringWriter; import java.io.IOException; import org.openscience.cdk.Molecule; import org.openscience.cdk.exception.CDKException; import org.openscience.cdk.io.MDLWriter; import org.openscience.cdk.smiles.SmilesParser; import org.openscience.cdk.layout.StructureDiagramGenerator; import org.openscience.cdk.tools.HydrogenAdder;

class smi2mol{

    public smi2mol(){
    }

    public String convert(String smi){
    Molecule mol = null;

    try {
        SmilesParser sp = new SmilesParser();
        mol = sp.parseSmiles(smi);
    }catch (Exception ise){
        ise.printStackTrace();
    }

    StringWriter w = null;
    MDLWriter  mw = null;

    try {
        w = new StringWriter();
        mw = new MDLWriter(w);
    } catch (Exception e) {
        e.printStackTrace();
    }

    HydrogenAdder ha = new HydrogenAdder();
    try{
        ha.addExplicitHydrogensToSatisfyValency(mol);
    } catch (Exception e){
        e.printStackTrace();
    }

    StructureDiagramGenerator sdg = new StructureDiagramGenerator();
        try{
        sdg.setMolecule(mol);
        sdg.generateCoordinates();
        mol = sdg.getMolecule();
        mw.write(mol);  
    } catch (Exception e){
        e.printStackTrace();
    }

    return w.toString();
    }
}

END_OF_JAVA_CODE

my $alu = new smi2mol();    
my $smiles_string = shift;
print $alu->convert($smiles_string);

実行してみる

::: sh $ perl test.pl "C(=O)O"

  CDK

  5  4  0  0  0  0  0  0  0  0999 V2000
    1.2990   -0.7500    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    0.0000    0.0000    0.0000 O   0  0  0  0  0  0  0  0  0  0  0  0
    2.5981   -0.0000    0.0000 O   0  0  0  0  0  0  0  0  0  0  0  0
    1.2990   -2.2500    0.0000 H   0  0  0  0  0  0  0  0  0  0  0  0
    3.8971   -0.7500    0.0000 H   0  0  0  0  0  0  0  0  0  0  0  0
  2  1  2  0  0  0  0 
  3  1  1  0  0  0  0 
  1  4  1  0  0  0  0 
  3  5  1  0  0  0  0 
M  END

水素が付加されて、座標も計算されたMOLファイルが出力される。

javaって例外を返す可能性がある場合try,catch構文入れないと強制的にエラーになるのね。try,catch構文は読みやすいけど、強制されんのはちょっとやだナァと。単にフォーマットをコンバートするだけのコードなのに結構長くなっちゃったし。

::: perl use CDK; use Chemistry::Mol;

my $mol = CDK::smi2sdf($molecule);
print $mol;

みたいにモジュールにしてuseして使えばCDKを意識しなくてよくなる。

CDKで吐かせたmolはChemrubyでの構造描画が?だヨ

ココのエントリでの構造描画は流れ的にChemrubyで描くべきなんだけど。

そもそも画像描画のステップには

  1. 2次元座標を保持したオブジェクトの生成
  2. 画像描画

が必要で、smilesのような座標情報のない形での構造情報は、何かで構造立ち上げしないといけない。chemrubyは立ち上げ処理できないらしいので、この作業は他の何かに任せるわけだ。 ちなみに、perlmolは芳香環が含まれない場合には、座標のついた形でmol形式に保存してくれるんだが、座標があったりなかったりとかはかなり使いにくいし、普通芳香環のない構造扱うことってあんまないでしょ?

な感じなので、CDKを使うのがデフォルト。

で、CDKで"OC=C-C=C"をmol形式にするとこうなる

  CDK

5  4  0  0  0  0  0  0  0  0999 V2000
    0.0000    0.0000    0.0000 O   0  0  0  0  0  0  0  0  0  0  0  0
    1.2990   -0.7500    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    2.5981   -0.0000    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    3.8971   -0.7500    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    5.1962   -0.0000    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
  2  1  1  0  0  0  0 
  3  2  2  0  0  0  0 
  4  3  1  0  0  0  0 
  5  4  2  0  0  0  0 
M  END

うまく座標が割り当てられてますな。これをchemrubyを使ってpngに変換するとこうなる

irb(main):001:0> require 'RMagick' => true irb(main):002:0> require 'chem' => true irb(main):003:0> mol = Chem.open_mol("diene.mol") irb(main):004:0> mol.save("rbtest.png")

rbtest

水酸基の情報が落ちてしまったヨ。

CDKで構造描画

smilesから二次元座標を立ち上げるには、CDKを使う。openbabelとかperlmolはここらへんが未実装。

StructureDiagramGenerator sdg = newStructureDiagramGenerator(); sdg.setMolecule(someMolecule); sdg.generateCoordinates(); Molecule layedOutMol = sdg.getMolecule();

これで二次元座標が起こせる。

さらに、org.openscience.cdk.rendererで構造をpngやjpgに書き出せる。

dopamine

でもCDKでも画像サイズを小さくするとサイズにあわせてダブルボンドの幅を小さくしたりフォントも綺麗に見えるように小さくなったりというような親切設計ではないんだよね。

dopamine

こんな風になってしまうな。今回eclipse使ってjavaで書いたけど、今後はこれをjythonで書き直す予定ダ。

CDKで構造描画(Linux)

linuxで二次元構造立ち上げる場合はXからの場合は問題ないが、ターミナルから起動するときにはjavaのAWTでこけるのでXvfbで仮想Xを起動してからprogramを動かす。FC1はXFree86-XvfbだけどFC2はxorg-x11-Xvfbだった。yumで入れられなくてちょっと悩んだ。

Linuxは画像出力サーバーとかCGIで使いたいからこの設定は必須でしょう。