mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-03 21:44:30 +08:00
* run clang-format-18 across Code/*.cpp and Code/*.h * run clang-format-18 across External
204 lines
4.8 KiB
C++
204 lines
4.8 KiB
C++
// $Id$
|
|
//
|
|
// Copyright (C) 2013 Greg Landrum
|
|
//
|
|
// @@ All Rights Reserved @@
|
|
// This file is part of the RDKit.
|
|
// The contents are covered by the terms of the BSD license
|
|
// which is included in the file license.txt, found at the root
|
|
// of the RDKit source tree.
|
|
//
|
|
|
|
#include <GraphMol/RDKitBase.h>
|
|
#include <GraphMol/Descriptors/MolDescriptors.h>
|
|
#include <GraphMol/Descriptors/Lipinski.h>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
|
|
namespace RDKit {
|
|
namespace Descriptors {
|
|
std::vector<unsigned int> calcMQNs(const ROMol &mol, bool) {
|
|
// FIX: use force value to enable caching
|
|
std::vector<unsigned int> res(42, 0);
|
|
|
|
// ---------------------------------------------------
|
|
// atom-centered things
|
|
// Note: We're not doing exactly the same thing
|
|
// as the original paper on polarity counts
|
|
// since we're using different donor and acceptor
|
|
// definitions.
|
|
ROMol::VERTEX_ITER atBegin, atEnd;
|
|
boost::tie(atBegin, atEnd) = mol.getVertices();
|
|
while (atBegin != atEnd) {
|
|
const Atom *at = mol[*atBegin];
|
|
++atBegin;
|
|
unsigned int nHs = at->getTotalNumHs();
|
|
unsigned int nRings = mol.getRingInfo()->numAtomRings(at->getIdx());
|
|
switch (at->getAtomicNum()) {
|
|
case 0:
|
|
case 1:
|
|
break;
|
|
case 6:
|
|
res[0]++;
|
|
break;
|
|
case 9:
|
|
res[1]++;
|
|
break;
|
|
case 17:
|
|
res[2]++;
|
|
break;
|
|
case 35:
|
|
res[3]++;
|
|
break;
|
|
case 53:
|
|
res[4]++;
|
|
break;
|
|
case 16:
|
|
res[5]++;
|
|
break;
|
|
case 15:
|
|
res[6]++;
|
|
break;
|
|
case 7:
|
|
if (!nRings) {
|
|
res[7]++;
|
|
} else {
|
|
res[8]++;
|
|
}
|
|
if (at->getDegree() != 4) {
|
|
res[19]++; // number of acceptor sites
|
|
res[20]++; // number of acceptor atoms
|
|
}
|
|
if (nHs) {
|
|
res[21] += nHs; // number of donor sites
|
|
res[22]++; // number of donor atoms
|
|
}
|
|
break;
|
|
case 8:
|
|
if (!nRings) {
|
|
res[9]++;
|
|
} else {
|
|
res[10]++;
|
|
}
|
|
res[20]++; // number of acceptor atoms
|
|
if (at->getFormalCharge() != -1) {
|
|
res[19] += 2; // number of acceptor sites
|
|
} else {
|
|
res[19] += 3; // number of acceptor sites
|
|
}
|
|
if (nHs) {
|
|
res[21] += nHs; // number of donor sites
|
|
res[22]++; // number of donor atoms
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (at->getFormalCharge() > 0) {
|
|
res[24]++; // positive charges
|
|
} else if (at->getFormalCharge() < 0) {
|
|
res[23]++; // negative charges
|
|
}
|
|
|
|
if (at->getAtomicNum() != 1) {
|
|
switch (at->getDegree()) {
|
|
case 1:
|
|
res[25]++;
|
|
break;
|
|
case 2:
|
|
if (!nRings) {
|
|
res[26]++;
|
|
} else {
|
|
res[29]++;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (!nRings) {
|
|
res[27]++;
|
|
} else {
|
|
res[30]++;
|
|
}
|
|
break;
|
|
case 4:
|
|
if (!nRings) {
|
|
res[28]++;
|
|
} else {
|
|
res[31]++;
|
|
}
|
|
break;
|
|
}
|
|
if (nRings >= 2) {
|
|
res[40]++;
|
|
}
|
|
}
|
|
}
|
|
res[11] = mol.getNumHeavyAtoms();
|
|
|
|
// ---------------------------------------------------
|
|
// bond counts:
|
|
unsigned int nAromatic = 0;
|
|
ROMol::EDGE_ITER firstB, lastB;
|
|
boost::tie(firstB, lastB) = mol.getEdges();
|
|
while (firstB != lastB) {
|
|
const Bond *bond = mol[*firstB];
|
|
if (bond->getIsAromatic()) {
|
|
++nAromatic;
|
|
}
|
|
unsigned int nRings = mol.getRingInfo()->numBondRings(bond->getIdx());
|
|
switch (bond->getBondType()) {
|
|
case Bond::SINGLE:
|
|
if (!nRings) {
|
|
res[12]++;
|
|
} else {
|
|
res[15]++;
|
|
}
|
|
break;
|
|
case Bond::DOUBLE:
|
|
if (!nRings) {
|
|
res[13]++;
|
|
} else {
|
|
res[16]++;
|
|
}
|
|
break;
|
|
case Bond::TRIPLE:
|
|
if (!nRings) {
|
|
res[14]++;
|
|
} else {
|
|
res[17]++;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (nRings >= 2) {
|
|
res[41]++;
|
|
}
|
|
++firstB;
|
|
}
|
|
// rather than do the work to kekulize the molecule, we cheat
|
|
// by just dividing the number of aromatic bonds evenly among the
|
|
// cyclic single bond and cyclic double bond bins and give any
|
|
// remainder to the single bonds
|
|
res[15] += nAromatic / 2;
|
|
res[16] += nAromatic / 2;
|
|
if (nAromatic % 2) {
|
|
res[15]++;
|
|
}
|
|
res[18] = calcNumRotatableBonds(mol);
|
|
|
|
// ---------------------------------------------------
|
|
// ring size counts
|
|
for (const auto &iv : mol.getRingInfo()->atomRings()) {
|
|
if (iv.size() < 10) {
|
|
res[iv.size() + 29]++;
|
|
} else {
|
|
res[39]++;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
} // end of namespace Descriptors
|
|
} // end of namespace RDKit
|