from enum import IntEnum
from itertools import chain
from rdkit import Chem
from ._base import Descriptor
from ._util import parse_enum
__all__ = ("BondCount",)
class BondType(IntEnum):
__slots__ = ()
any = 1
heavy = 2
single = 3
double = 4
triple = 5
aromatic = 6
multiple = 7
@property
def as_argument(self):
return self.name
bond_types = (
(BondType.any, ("", "all bonds", lambda _: True)),
(BondType.heavy, ("O", "bonds connecting to heavy atom", lambda _: True)),
(
BondType.single,
("S", "single bonds", lambda b: b.GetBondType() == Chem.BondType.SINGLE),
),
(
BondType.double,
("D", "double bonds", lambda b: b.GetBondType() == Chem.BondType.DOUBLE),
),
(
BondType.triple,
("T", "triple bonds", lambda b: b.GetBondType() == Chem.BondType.TRIPLE),
),
(
BondType.aromatic,
(
"A",
"aromatic bonds",
lambda b: b.GetIsAromatic() or b.GetBondType() == Chem.BondType.AROMATIC,
),
),
(
BondType.multiple,
(
"M",
"multiple bonds",
lambda b: b.GetIsAromatic() or b.GetBondType() != Chem.BondType.SINGLE,
),
),
)
bond_type_dict = dict(bond_types)
[docs]
class BondCount(Descriptor):
r"""bond count descriptor.
:type type: str
:param type: one of bond_types
:type kekulize: bool
:param kekulize: use kekulized structure
"""
since = "1.0.0"
__slots__ = ("_type", "_bond_name", "_bond_desc", "_check_bond", "kekulize")
[docs]
def description(self):
return "number of {} in {}kekulized structure".format(
self._bond_desc, "" if self.kekulize else "non-"
)
bond_types = tuple(b.name for b in BondType)
@classmethod
def preset(cls, version):
return chain(
map(lambda t: cls(t, False), BondType),
map(lambda t: cls(t, True), [BondType.single, BondType.double]),
)
def __str__(self):
K = "K" if self.kekulize else ""
return "nBonds{}{}".format(K, self._bond_name)
@property
def explicit_hydrogens(self):
return self._type in (BondType.any, BondType.single)
def parameters(self):
return self._type, self.kekulize
def __init__(self, type="any", kekulize=False):
self._type = parse_enum(BondType, type)
self._bond_name, self._bond_desc, self._check_bond = bond_type_dict[self._type]
self.kekulize = kekulize
def calculate(self):
return sum(1 for b in self.mol.GetBonds() if self._check_bond(b))
rtype = int
_extra_docs = ("bond_types",)