19#include <boost/dynamic_bitset.hpp>
35 unsigned int bondStereo{
36 static_cast<unsigned int>(Bond::BondStereo::STEREONONE)};
37 unsigned int nbrSymClass{0};
38 unsigned int nbrIdx{0};
40 const canon_atom *controllingAtoms[4]{
nullptr,
nullptr,
nullptr,
nullptr};
41 const std::string *p_symbol{
43 unsigned int bondIdx{0};
47 unsigned int nsc,
unsigned int bidx)
49 bondStereo(static_cast<unsigned int>(bs)),
54 unsigned int nsc,
unsigned int bidx)
65 return compare(lhs, rhs) > 0;
69 unsigned int div = 1) {
103 unsigned int degree{0};
104 unsigned int totalNumHs{0};
105 bool hasRingNbr{
false};
106 bool isRingStereoAtom{
false};
107 unsigned int whichStereoGroup{0};
110 const std::string *p_symbol{
122 std::vector<std::pair<unsigned int, unsigned int>> &
result);
139 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
140 *dp_bondsInPlay{
nullptr};
145 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
146 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
149 dp_atomsInPlay(atomsInPlay),
150 dp_bondsInPlay(bondsInPlay) {}
155 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
159 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
162 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
165 for (
unsigned int ii = 0;
166 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
168 bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]);
174 std::vector<std::pair<unsigned int, unsigned int>> swapsi;
175 std::vector<std::pair<unsigned int, unsigned int>> swapsj;
176 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
179 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
182 for (
unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) {
183 int cmp = swapsi[ii].second - swapsj[ii].second;
196 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
197 *dp_bondsInPlay{
nullptr};
202 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
203 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
206 dp_atomsInPlay(atomsInPlay),
207 dp_bondsInPlay(bondsInPlay) {}
212 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
216 if (dp_atoms[i].neighborNum < dp_atoms[j].neighborNum) {
218 }
else if (dp_atoms[i].neighborNum > dp_atoms[j].neighborNum) {
222 if (dp_atoms[i].revistedNeighbors < dp_atoms[j].revistedNeighbors) {
224 }
else if (dp_atoms[i].revistedNeighbors > dp_atoms[j].revistedNeighbors) {
228 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
231 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
234 for (
unsigned int ii = 0;
235 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
237 bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]);
243 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
245 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
255 unsigned int res = 0;
256 std::vector<unsigned int>
perm;
257 perm.reserve(dp_atoms[i].atom->getDegree());
258 for (
const auto nbr : dp_mol->atomNeighbors(dp_atoms[i].atom)) {
259 auto rnk = dp_atoms[
nbr->getIdx()].index;
267 if (
perm.size() == dp_atoms[i].atom->getDegree()) {
268 auto ctag = dp_atoms[i].atom->getChiralTag();
284 unsigned int getAtomRingNbrCode(
unsigned int i)
const {
285 if (!dp_atoms[i].hasRingNbr) {
289 auto nbrs = dp_atoms[i].nbrIds.get();
290 unsigned int code = 0;
291 for (
unsigned j = 0; j < dp_atoms[i].degree; ++j) {
292 if (dp_atoms[nbrs[j]].isRingStereoAtom) {
293 code += dp_atoms[nbrs[j]].index * 10000 + 1;
299 int basecomp(
int i,
int j)
const {
300 unsigned int ivi, ivj;
303 ivi = dp_atoms[i].index;
304 ivj = dp_atoms[j].index;
307 }
else if (ivi > ivj) {
310 if (df_useAtomMaps) {
312 int molAtomMapNumber_i = 0;
313 int molAtomMapNumber_j = 0;
314 dp_atoms[i].atom->getPropIfPresent(common_properties::molAtomMapNumber,
316 dp_atoms[j].atom->getPropIfPresent(common_properties::molAtomMapNumber,
318 if (molAtomMapNumber_i < molAtomMapNumber_j) {
320 }
else if (molAtomMapNumber_i > molAtomMapNumber_j) {
325 ivi = dp_atoms[i].degree;
326 ivj = dp_atoms[j].degree;
329 }
else if (ivi > ivj) {
332 if (dp_atoms[i].p_symbol && dp_atoms[j].p_symbol) {
333 if (*(dp_atoms[i].p_symbol) < *(dp_atoms[j].p_symbol)) {
335 }
else if (*(dp_atoms[i].p_symbol) > *(dp_atoms[j].p_symbol)) {
343 ivi = dp_atoms[i].atom->getAtomicNum();
344 ivj = dp_atoms[j].atom->getAtomicNum();
347 }
else if (ivi > ivj) {
351 if (df_useIsotopes) {
352 ivi = dp_atoms[i].atom->getIsotope();
353 ivj = dp_atoms[j].atom->getIsotope();
356 }
else if (ivi > ivj) {
362 ivi = dp_atoms[i].totalNumHs;
363 ivj = dp_atoms[j].totalNumHs;
366 }
else if (ivi > ivj) {
370 ivi = dp_atoms[i].atom->getFormalCharge();
371 ivj = dp_atoms[j].atom->getFormalCharge();
374 }
else if (ivi > ivj) {
378 if (df_useChiralPresence) {
380 dp_atoms[i].atom->getChiralTag() != Atom::ChiralType::CHI_UNSPECIFIED;
382 dp_atoms[j].atom->getChiralTag() != Atom::ChiralType::CHI_UNSPECIFIED;
385 }
else if (ivi > ivj) {
390 if (df_useChirality) {
392 ivi = dp_atoms[i].whichStereoGroup;
394 ivj = dp_atoms[j].whichStereoGroup;
398 }
else if (ivj && !ivi) {
400 }
else if (ivi && ivj) {
401 ivi =
static_cast<unsigned int>(dp_atoms[i].typeOfStereoGroup);
402 ivj =
static_cast<unsigned int>(dp_atoms[j].typeOfStereoGroup);
405 }
else if (ivi > ivj) {
408 ivi = dp_atoms[i].whichStereoGroup - 1;
409 ivj = dp_atoms[j].whichStereoGroup - 1;
411 std::set<unsigned int> sgi;
413 sgi.insert(dp_atoms[sgat->getIdx()].index);
415 std::set<unsigned int> sgj;
417 sgj.insert(dp_atoms[sgat->getIdx()].index);
421 }
else if (sgi > sgj) {
431 ivi = dp_atoms[i].atom->getChiralTag() != 0;
432 ivj = dp_atoms[j].atom->getChiralTag() != 0;
435 }
else if (ivi > ivj) {
441 ivi = getChiralRank(dp_mol, dp_atoms, i);
444 ivj = getChiralRank(dp_mol, dp_atoms, j);
448 }
else if (ivi > ivj) {
455 if (df_useChiralityRings) {
457 ivi = getAtomRingNbrCode(i);
458 ivj = getAtomRingNbrCode(j);
461 }
else if (ivi > ivj) {
471 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
472 *dp_bondsInPlay{
nullptr};
473 bool df_useNbrs{
false};
474 bool df_useIsotopes{
true};
475 bool df_useChirality{
true};
476 bool df_useChiralityRings{
true};
477 bool df_useAtomMaps{
true};
478 bool df_useChiralPresence{
true};
482 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
483 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
486 dp_atomsInPlay(atomsInPlay),
487 dp_bondsInPlay(bondsInPlay) {}
489 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
492 int v = basecomp(i, j);
498 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
501 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
505 for (
unsigned int ii = 0;
506 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
509 bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]);
515 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
517 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
532 void getAtomNeighborhood(std::vector<bondholder> &nbrs)
const {
533 for (
unsigned j = 0; j < nbrs.size(); ++j) {
534 unsigned int nbrIdx = nbrs[j].nbrIdx;
539 const Atom *nbr = dp_atoms[nbrIdx].atom;
540 nbrs[j].nbrSymClass =
543 std::sort(nbrs.begin(), nbrs.end(), bondholder::greater);
547 int basecomp(
int i,
int j)
const {
549 unsigned int ivi, ivj;
552 ivi = dp_atoms[i].index;
553 ivj = dp_atoms[j].index;
556 }
else if (ivi > ivj) {
561 ivi = dp_atoms[i].atom->getAtomicNum();
562 ivj = dp_atoms[j].atom->getAtomicNum();
565 }
else if (ivi > ivj) {
570 ivi = dp_atoms[i].atom->getIsotope();
571 ivj = dp_atoms[j].atom->getIsotope();
574 }
else if (ivi > ivj) {
582 if (dp_atoms[i].atom->getPropIfPresent(common_properties::_CIPCode,
584 ivi = cipCode ==
"R" ? 2 : 1;
586 if (dp_atoms[j].atom->getPropIfPresent(common_properties::_CIPCode,
588 ivj = cipCode ==
"R" ? 2 : 1;
592 }
else if (ivi > ivj) {
603 bool df_useNbrs{
false};
606 : dp_atoms(atoms), dp_mol(&m), df_useNbrs(false) {}
611 int v = basecomp(i, j);
617 getAtomNeighborhood(dp_atoms[i].bonds);
618 getAtomNeighborhood(dp_atoms[j].bonds);
623 for (
unsigned int ii = 0;
624 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
626 int cmp = bondholder::compare(
632 for (
unsigned int ii = 0;
633 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
636 bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]);
641 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
643 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
656template <
typename CompareFunc>
689 start = order + offset;
707 for (
int k = 0;
k <
len; ++
k) {
714 for (i =
count[index]; i <
len; i++) {
724 for (
unsigned j = 0;
j < atoms[index].
degree; ++
j) {
732 for (i =
count[index]; i <
len; i++) {
734 for (
unsigned j = 0;
j < atoms[index].
degree; ++
j) {
753template <
typename CompareFunc>
764 for (
unsigned int i = 0; i <
nAtoms; i++) {
770 index = order[offset];
771 atoms[index].
index = offset;
776 if (atoms[index].degree < 1) {
779 for (
unsigned j = 0;
j < atoms[index].
degree; ++
j) {
806 int *order,
int *
count,
814 const ROMol &mol, std::vector<unsigned int> &
res,
bool breakTies =
true,
820 const ROMol &mol, std::vector<unsigned int> &
res,
823 const std::vector<std::string> *atomSymbols,
824 const std::vector<std::string> *
bondSymbols,
bool breakTies,
829 const ROMol &mol, std::vector<unsigned int> &
res,
832 const std::vector<std::string> *atomSymbols =
nullptr,
842 std::vector<unsigned int> &
res);
845 std::vector<Canon::canon_atom> &atoms,
851 std::vector<Canon::canon_atom> &atoms,
853 const std::vector<std::string> *atomSymbols,
860 bool useSpecial =
false,
bool useChirality =
false,
861 const boost::dynamic_bitset<> *
atomsInPlay =
nullptr,
862 const boost::dynamic_bitset<> *
bondsInPlay =
nullptr);
#define PRECONDITION(expr, mess)
Defines the primary molecule class ROMol as well as associated typedefs.
Defines the class StereoGroup which stores relationships between the absolute configurations of atoms...
The class for representing atoms.
int getAtomicNum() const
returns our atomic number
@ CHI_TETRAHEDRAL_CW
tetrahedral: clockwise rotation (SMILES @@)
@ CHI_TETRAHEDRAL_CCW
tetrahedral: counter-clockwise rotation (SMILES
BondStereo
the nature of the bond's stereochem (for cis/trans)
AtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=nullptr, const boost::dynamic_bitset<> *bondsInPlay=nullptr)
int operator()(int i, int j) const
ChiralAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m)
int operator()(int i, int j) const
ChiralAtomCompareFunctor()
int operator()(int i, int j) const
SpecialChiralityAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=nullptr, const boost::dynamic_bitset<> *bondsInPlay=nullptr)
SpecialChiralityAtomCompareFunctor()
SpecialSymmetryAtomCompareFunctor()
SpecialSymmetryAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=nullptr, const boost::dynamic_bitset<> *bondsInPlay=nullptr)
int operator()(int i, int j) const
const std::vector< StereoGroup > & getStereoGroups() const
Gets a reference to the groups of atoms with relative stereochemistry.
unsigned int getNumAtoms() const
returns our number of atoms
#define RDKIT_GRAPHMOL_EXPORT
void rankWithFunctor(T &ftor, bool breakTies, int *order, bool useSpecial=false, bool useChirality=false, const boost::dynamic_bitset<> *atomsInPlay=nullptr, const boost::dynamic_bitset<> *bondsInPlay=nullptr)
void initFragmentCanonAtoms(const ROMol &mol, std::vector< Canon::canon_atom > &atoms, bool includeChirality, const std::vector< std::string > *atomSymbols, const std::vector< std::string > *bondSymbols, const boost::dynamic_bitset<> &atomsInPlay, const boost::dynamic_bitset<> &bondsInPlay, bool needsInit)
RDKIT_GRAPHMOL_EXPORT void rankMolAtoms(const ROMol &mol, std::vector< unsigned int > &res, bool breakTies=true, bool includeChirality=true, bool includeIsotopes=true, bool includeAtomMaps=true, bool includeChiralPresence=false, bool includeStereoGroups=true)
RDKIT_GRAPHMOL_EXPORT void initCanonAtoms(const ROMol &mol, std::vector< Canon::canon_atom > &atoms, bool includeChirality=true, bool includeStereoGroups=true)
RDKIT_GRAPHMOL_EXPORT void CreateSinglePartition(unsigned int nAtoms, int *order, int *count, canon_atom *atoms)
RDKIT_GRAPHMOL_EXPORT void rankFragmentAtoms(const ROMol &mol, std::vector< unsigned int > &res, const boost::dynamic_bitset<> &atomsInPlay, const boost::dynamic_bitset<> &bondsInPlay, const std::vector< std::string > *atomSymbols, const std::vector< std::string > *bondSymbols, bool breakTies, bool includeChirality, bool includeIsotope, bool includeAtomMaps, bool includeChiralPresence)
RDKIT_GRAPHMOL_EXPORT void ActivatePartitions(unsigned int nAtoms, int *order, int *count, int &activeset, int *next, int *changed)
const unsigned int ATNUM_CLASS_OFFSET
RDKIT_GRAPHMOL_EXPORT void updateAtomNeighborNumSwaps(canon_atom *atoms, std::vector< bondholder > &nbrs, unsigned int atomIdx, std::vector< std::pair< unsigned int, unsigned int > > &result)
void BreakTies(const ROMol &mol, canon_atom *atoms, CompareFunc compar, int mode, int *order, int *count, int &activeset, int *next, int *changed, char *touchedPartitions)
void RefinePartitions(const ROMol &mol, canon_atom *atoms, CompareFunc compar, int mode, int *order, int *count, int &activeset, int *next, int *changed, char *touchedPartitions)
RDKIT_GRAPHMOL_EXPORT void chiralRankMolAtoms(const ROMol &mol, std::vector< unsigned int > &res)
RDKIT_GRAPHMOL_EXPORT void updateAtomNeighborIndex(canon_atom *atoms, std::vector< bondholder > &nbrs)
bool rdvalue_is(const RDValue_cast_t)
void hanoisort(int *base, int nel, int *count, int *changed, CompareFunc compar)
unsigned int countSwapsToInterconvert(const T &ref, T probe)
const std::string * p_symbol
static bool greater(const bondholder &lhs, const bondholder &rhs)
bool operator<(const bondholder &o) const
int compareStereo(const bondholder &o) const
bondholder(Bond::BondType bt, unsigned int bs, unsigned int ni, unsigned int nsc, unsigned int bidx)
bondholder(Bond::BondType bt, Bond::BondStereo bs, unsigned int ni, unsigned int nsc, unsigned int bidx)
static int compare(const bondholder &x, const bondholder &y, unsigned int div=1)
std::vector< bondholder > bonds
std::unique_ptr< int[]> nbrIds
std::vector< int > revistedNeighbors
std::vector< int > neighborNum