Canonical SMILES

ふたつの化学構造が同一構造なのか、手っ取り早く知りたいとき、
"Canonical (正準化された)" SMILES形式を使うと便利です。


化学構造を"通常の"SMILES形式で表現しようとすると、一意に定まらないことがあります。
たとえば、エーテル(diethyl ether)の場合、

CCOCC
C(C)OCC
C(OCC)C
O(CC)CC

のように、記述の開始点と順序により、4通りの表現が可能です。
そこで、これらの中からひとつ代表SMILESに統一しよう、そうすれば
文字列の一致が化学構造の一致に対応付けられる、というのが"Canonical"の考え方です。


さて、ここからは実装の話で、私も最近知ったことなのですが、
あるソフトで"Canonical"であったとしても、別のソフトでそうとは限りません。
ソフトによって、それぞれ"Canonical"の定義が存在するようなのです。
(これに気づいたのは、OpenBabelのver.2.2.0 と ver.2.3.0 の間の相違でした)
たとえば、OpenBabelとCDKの間でも、出力結果が異なります。


CDKの場合、以下のスクリプトで、SDF形式からCanonical SMILES形式に変換できます。


/* sdf2can.java */

import java.io.*;
import org.openscience.cdk.interfaces.*;
import org.openscience.cdk.io.iterator.IteratingMDLReader;
import org.openscience.cdk.DefaultChemObjectBuilder;

import org.openscience.cdk.smiles.SmilesGenerator;
import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;

class sdf2can {

public static void main(String args[]){

if(args.length!=1){
System.err.println("sdf2can <sd-file>");
System.exit(1);
}
FileInputStream fis = null;
IteratingMDLReader isr = null;
try{
fis = new FileInputStream(new File(args[0]) );
isr = new IteratingMDLReader(fis, DefaultChemObjectBuilder.getInstance() );
} catch (Exception e) {
e.printStackTrace();
}

while( isr.hasNext() ){
IMolecule imol = (IMolecule)isr.next();
String id = (String)imol.getProperty("cdk:Title");
SmilesGenerator sg = new SmilesGenerator();
AtomContainerManipulator acm = new AtomContainerManipulator();
try {
sg.setUseAromaticityFlag(true);
String can = sg.createSMILES(acm.removeHydrogens(imol));
System.out.printf("%s\t%s\n", can, id);
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
}

次回では、CDKにおける"Canonical"の定義について、追いかけてみようと思います。