回転可能結合数

なぜ、CDKのRuleOfFiveDescriptorクラスで「回転可能結合数」が数えられているのか、
推察してみましたところ、Veberらの論文*1 に行き当たりました。
彼らは、リピンスキーの法則の拡張を考え、結果として、

  • 回転可能結合数 ≦ 10
  • 極性表面積 ≦ 140 (Å^2)

が目安となることを見つけたのでした。


回転可能結合数は、動物の骨格で言えば、ちょうど関節の数のようなものです。ヘビの背骨の関節は200近くもあるそうで、それゆえ、クネクネと動くことができます。同じように、回転可能結合数が大きいと、分子の柔軟性(flexibility)が高くなる傾向にあります。ただ、分子の場合は能動的に変形できないので、柔軟性がむしろ仇となって、細胞膜をスムーズに通過できず、結果として吸収率が低下する、と考えられているようです。


おそらくCDKは、Veberらの結果を部分的に踏襲しているのでしょう。
さて、回転可能結合数が登場したところで、さっそく数えてみましょう。


/* rotBond.java */

import java.io.*;
import org.openscience.cdk.io.iterator.IteratingSMILESReader;
import org.openscience.cdk.interfaces.IMolecule;
import org.openscience.cdk.qsar.IMolecularDescriptor;

import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.annotations.TestClass;
import org.openscience.cdk.annotations.TestMethod;
import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.exception.NoSuchAtomException;
import org.openscience.cdk.graph.SpanningTree;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IBond;
import org.openscience.cdk.interfaces.IRingSet;
import org.openscience.cdk.qsar.DescriptorSpecification;
import org.openscience.cdk.qsar.DescriptorValue;
import org.openscience.cdk.qsar.IMolecularDescriptor;
import org.openscience.cdk.qsar.result.IDescriptorResult;
import org.openscience.cdk.tools.manipulator.BondManipulator;
import java.util.List;

class rotBond {
public static void main(String args[]){

if(args.length!=1){
System.err.println("rotBond <smiles-file>");
System.exit(1);
}
FileInputStream fis = null;
IteratingSMILESReader isr = null;
try{
fis = new FileInputStream(new File(args[0]));
isr = new IteratingSMILESReader(fis);
} catch (Exception e) {
e.printStackTrace();
}

while( isr.hasNext() ){ // Read a file line by line
IMolecule imol = (IMolecule)isr.next();
String id = (String)imol.getProperty("cdk:Title"); // The 2nd column

boolean includeTerminals = false;
int rotatableBondsCount = 0;
int rotatableBondsCount2 = 0;
int degree0;
int degree1;
IRingSet ringSet;
try{
ringSet = new SpanningTree(imol).getBasicRings();
for (IBond bond : imol.bonds()) {
if (ringSet.getRings(bond).getAtomContainerCount() > 0) {
bond.setFlag(CDKConstants.ISINRING, true);
}
}

for (IBond bond : imol.bonds()) {
IAtom atom0 = bond.getAtom(0);
IAtom atom1 = bond.getAtom(1);
if (atom0.getSymbol().equals("H") ) continue;
if ( atom1.getSymbol().equals("H")) continue;
if (bond.getOrder() != CDKConstants.BONDORDER_SINGLE) continue;
if ( ! BondManipulator.isLowerOrder(imol.getMaximumBondOrder(atom0),
IBond.Order.TRIPLE)) continue;
if ( ! BondManipulator.isLowerOrder(imol.getMaximumBondOrder(atom1),
IBond.Order.TRIPLE)) continue;
if ( bond.getFlag(CDKConstants.ISINRING) ) continue;

// if there are explicit H's we should ignore those bonds
degree0 = imol.getConnectedBondsCount(atom0) -
getConnectedHCount(imol, atom0);
degree1 = imol.getConnectedBondsCount(atom1) -
getConnectedHCount(imol, atom1);
if ( (degree0 == 1) || (degree1 == 1) ) {
if ( includeTerminals ) {
rotatableBondsCount += 1;
}
} else {
rotatableBondsCount += 1;
}
}
} catch (Exception e1) {
e1.printStackTrace();
}
System.out.printf("%s\t%d\n", id, rotatableBondsCount );
}
}

private static int getConnectedHCount(IAtomContainer atomContainer, IAtom atom) {
List<IAtom> connectedAtoms = atomContainer.getConnectedAtomsList(atom);
int n = 0;
for (IAtom anAtom : connectedAtoms) if (anAtom.getSymbol().equals("H")) n++;
return n;
}
}

判定条件としては、

  • 一重結合である
  • 両端の原子は水素ではない
  • 三重結合に隣接していない
  • 環構造の一部ではない

があります。確かにそのような気がしますね。

*1: Veber et al.Molecular Properties That Influence the Oral Bioavailability of Drug Candidates. J. Med. Chem. (2002) 45, 2615-2623 PubMed