18 #include <boost/dynamic_bitset.hpp>
34 unsigned int bondStereo{
35 static_cast<unsigned int>(Bond::BondStereo::STEREONONE)};
36 unsigned int nbrSymClass{0};
37 unsigned int nbrIdx{0};
39 const canon_atom *controllingAtoms[4]{
nullptr,
nullptr,
nullptr,
nullptr};
40 const std::string *p_symbol{
42 unsigned int bondIdx{0};
46 unsigned int nsc,
unsigned int bidx)
48 bondStereo(static_cast<unsigned int>(bs)),
53 unsigned int nsc,
unsigned int bidx)
64 return compare(lhs, rhs) > 0;
68 unsigned int div = 1) {
103 unsigned int degree{0};
104 unsigned int totalNumHs{0};
105 bool hasRingNbr{
false};
106 bool isRingStereoAtom{
false};
107 int *nbrIds{
nullptr};
108 const std::string *p_symbol{
120 canon_atom *atoms, std::vector<bondholder> &nbrs);
123 canon_atom *atoms, std::vector<bondholder> &nbrs,
unsigned int atomIdx,
124 std::vector<std::pair<unsigned int, unsigned int>> &result);
141 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
142 *dp_bondsInPlay{
nullptr};
147 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
148 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
151 dp_atomsInPlay(atomsInPlay),
152 dp_bondsInPlay(bondsInPlay) {}
157 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
161 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
164 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
167 for (
unsigned int ii = 0;
168 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
176 std::vector<std::pair<unsigned int, unsigned int>> swapsi;
177 std::vector<std::pair<unsigned int, unsigned int>> swapsj;
178 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
181 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
184 for (
unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) {
185 int cmp = swapsi[ii].second - swapsj[ii].second;
198 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
199 *dp_bondsInPlay{
nullptr};
204 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
205 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
208 dp_atomsInPlay(atomsInPlay),
209 dp_bondsInPlay(bondsInPlay) {}
214 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
218 if (dp_atoms[i].neighborNum < dp_atoms[j].neighborNum) {
220 }
else if (dp_atoms[i].neighborNum > dp_atoms[j].neighborNum) {
224 if (dp_atoms[i].revistedNeighbors < dp_atoms[j].revistedNeighbors) {
226 }
else if (dp_atoms[i].revistedNeighbors > dp_atoms[j].revistedNeighbors) {
230 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
233 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
236 for (
unsigned int ii = 0;
237 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
245 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
247 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
255 unsigned int getChiralRank(
const ROMol *dp_mol, canon_atom *dp_atoms,
257 unsigned int res = 0;
258 std::vector<unsigned int> perm;
259 perm.reserve(dp_atoms[i].atom->getDegree());
260 for (
const auto nbr : dp_mol->
atomNeighbors(dp_atoms[i].atom)) {
261 auto rnk = dp_atoms[nbr->getIdx()].index;
263 if (std::find(perm.begin(), perm.end(), rnk) != perm.end()) {
269 if (perm.size() == dp_atoms[i].atom->getDegree()) {
270 auto ctag = dp_atoms[i].atom->getChiralTag();
271 if (ctag == Atom::ChiralType::CHI_TETRAHEDRAL_CW ||
272 ctag == Atom::ChiralType::CHI_TETRAHEDRAL_CCW) {
273 auto sortedPerm = perm;
274 std::sort(sortedPerm.begin(), sortedPerm.end());
276 res = ctag == Atom::ChiralType::CHI_TETRAHEDRAL_CW ? 2 : 1;
278 res = res == 2 ? 1 : 2;
286 unsigned int getAtomRingNbrCode(
unsigned int i)
const {
287 if (!dp_atoms[i].hasRingNbr) {
291 int *nbrs = dp_atoms[i].nbrIds;
292 unsigned int code = 0;
293 for (
unsigned j = 0; j < dp_atoms[i].degree; ++j) {
294 if (dp_atoms[nbrs[j]].isRingStereoAtom) {
295 code += dp_atoms[nbrs[j]].index * 10000 + 1;
301 int basecomp(
int i,
int j)
const {
302 unsigned int ivi, ivj;
305 ivi = dp_atoms[i].index;
306 ivj = dp_atoms[j].index;
309 }
else if (ivi > ivj) {
317 int molAtomMapNumber_i = 0;
318 int molAtomMapNumber_j = 0;
323 if (molAtomMapNumber_i < molAtomMapNumber_j) {
325 }
else if (molAtomMapNumber_i > molAtomMapNumber_j) {
329 ivi = dp_atoms[i].degree;
330 ivj = dp_atoms[j].degree;
333 }
else if (ivi > ivj) {
336 if (dp_atoms[i].p_symbol && dp_atoms[j].p_symbol) {
337 if (*(dp_atoms[i].p_symbol) < *(dp_atoms[j].p_symbol)) {
339 }
else if (*(dp_atoms[i].p_symbol) > *(dp_atoms[j].p_symbol)) {
347 ivi = dp_atoms[i].atom->getAtomicNum();
348 ivj = dp_atoms[j].atom->getAtomicNum();
351 }
else if (ivi > ivj) {
355 if (df_useIsotopes) {
356 ivi = dp_atoms[i].atom->getIsotope();
357 ivj = dp_atoms[j].atom->getIsotope();
360 }
else if (ivi > ivj) {
366 ivi = dp_atoms[i].totalNumHs;
367 ivj = dp_atoms[j].totalNumHs;
370 }
else if (ivi > ivj) {
374 ivi = dp_atoms[i].atom->getFormalCharge();
375 ivj = dp_atoms[j].atom->getFormalCharge();
378 }
else if (ivi > ivj) {
382 if (df_useChirality) {
387 ivi = dp_atoms[i].atom->getChiralTag() != 0;
388 ivj = dp_atoms[j].atom->getChiralTag() != 0;
391 }
else if (ivi > ivj) {
397 ivi = getChiralRank(dp_mol, dp_atoms, i);
400 ivj = getChiralRank(dp_mol, dp_atoms, j);
404 }
else if (ivi > ivj) {
410 if (df_useChiralityRings) {
412 ivi = getAtomRingNbrCode(i);
413 ivj = getAtomRingNbrCode(j);
416 }
else if (ivi > ivj) {
426 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
427 *dp_bondsInPlay{
nullptr};
428 bool df_useNbrs{
false};
429 bool df_useIsotopes{
true};
430 bool df_useChirality{
true};
431 bool df_useChiralityRings{
true};
435 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
436 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
439 dp_atomsInPlay(atomsInPlay),
440 dp_bondsInPlay(bondsInPlay),
442 df_useIsotopes(true),
443 df_useChirality(true),
444 df_useChiralityRings(true) {}
446 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
449 int v = basecomp(i, j);
455 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
458 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
462 for (
unsigned int ii = 0;
463 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
472 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
474 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
489 void getAtomNeighborhood(std::vector<bondholder> &nbrs)
const {
490 for (
unsigned j = 0; j < nbrs.size(); ++j) {
491 unsigned int nbrIdx = nbrs[j].nbrIdx;
496 const Atom *nbr = dp_atoms[nbrIdx].atom;
497 nbrs[j].nbrSymClass =
504 int basecomp(
int i,
int j)
const {
506 unsigned int ivi, ivj;
509 ivi = dp_atoms[i].index;
510 ivj = dp_atoms[j].index;
513 }
else if (ivi > ivj) {
518 ivi = dp_atoms[i].atom->getAtomicNum();
519 ivj = dp_atoms[j].atom->getAtomicNum();
522 }
else if (ivi > ivj) {
527 ivi = dp_atoms[i].atom->getIsotope();
528 ivj = dp_atoms[j].atom->getIsotope();
531 }
else if (ivi > ivj) {
541 ivi = cipCode ==
"R" ? 2 : 1;
545 ivj = cipCode ==
"R" ? 2 : 1;
549 }
else if (ivi > ivj) {
560 bool df_useNbrs{
false};
563 : dp_atoms(atoms), dp_mol(&m), df_useNbrs(false) {}
568 int v = basecomp(i, j);
574 getAtomNeighborhood(dp_atoms[i].bonds);
575 getAtomNeighborhood(dp_atoms[j].bonds);
580 for (
unsigned int ii = 0;
581 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
589 for (
unsigned int ii = 0;
590 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
598 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
600 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
613 template <
typename CompareFunc>
615 int mode,
int *order,
int *count,
int &activeset,
616 int *next,
int *changed,
char *touchedPartitions) {
628 while (activeset != -1) {
640 partition = activeset;
641 activeset = next[partition];
642 next[partition] = -2;
644 len = count[partition];
645 offset = atoms[partition].
index;
646 start = order + offset;
657 hanoisort(start, len, count, changed, compar);
664 for (
int k = 0; k < len; ++k) {
665 changed[start[k]] = 0;
671 for (i = count[index]; i < len; i++) {
674 symclass = offset + i;
676 atoms[index].
index = symclass;
681 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
682 changed[atoms[index].
nbrIds[j]] = 1;
689 for (i = count[index]; i < len; i++) {
691 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
692 unsigned int nbor = atoms[index].
nbrIds[j];
693 touchedPartitions[atoms[nbor].
index] = 1;
696 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
697 if (touchedPartitions[ii]) {
698 partition = order[ii];
699 if ((count[partition] > 1) && (next[partition] == -2)) {
700 next[partition] = activeset;
701 activeset = partition;
703 touchedPartitions[ii] = 0;
710 template <
typename CompareFunc>
712 int mode,
int *order,
int *count,
int &activeset,
int *next,
713 int *changed,
char *touchedPartitions) {
721 for (
unsigned int i = 0; i < nAtoms; i++) {
722 partition = order[i];
723 oldPart = atoms[partition].
index;
724 while (count[partition] > 1) {
725 len = count[partition];
726 offset = atoms[partition].
index + len - 1;
727 index = order[offset];
728 atoms[index].
index = offset;
729 count[partition] = len - 1;
733 if (atoms[index].degree < 1) {
736 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
737 unsigned int nbor = atoms[index].
nbrIds[j];
738 touchedPartitions[atoms[nbor].
index] = 1;
742 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
743 if (touchedPartitions[ii]) {
744 int npart = order[ii];
745 if ((count[npart] > 1) && (next[npart] == -2)) {
746 next[npart] = activeset;
749 touchedPartitions[ii] = 0;
753 changed, touchedPartitions);
756 if (atoms[partition].index != oldPart) {
763 int *order,
int *count,
767 int *count,
int &activeset,
768 int *next,
int *changed);
771 std::vector<unsigned int> &res,
772 bool breakTies =
true,
773 bool includeChirality =
true,
774 bool includeIsotopes =
true);
777 const ROMol &mol, std::vector<unsigned int> &res,
778 const boost::dynamic_bitset<> &atomsInPlay,
779 const boost::dynamic_bitset<> &bondsInPlay,
780 const std::vector<std::string> *atomSymbols,
781 const std::vector<std::string> *bondSymbols,
bool breakTies,
782 bool includeChirality,
bool includeIsotope);
785 const ROMol &mol, std::vector<unsigned int> &res,
786 const boost::dynamic_bitset<> &atomsInPlay,
787 const boost::dynamic_bitset<> &bondsInPlay,
788 const std::vector<std::string> *atomSymbols =
nullptr,
789 bool breakTies =
true,
bool includeChirality =
true,
790 bool includeIsotopes =
true) {
792 breakTies, includeChirality, includeIsotopes);
796 std::vector<unsigned int> &res);
799 std::vector<Canon::canon_atom> &atoms,
800 bool includeChirality =
true);
804 std::vector<Canon::canon_atom> &atoms,
805 bool includeChirality,
806 const std::vector<std::string> *atomSymbols,
807 const std::vector<std::string> *bondSymbols,
808 const boost::dynamic_bitset<> &atomsInPlay,
809 const boost::dynamic_bitset<> &bondsInPlay,
812 template <
typename T>
814 bool useSpecial =
false,
bool useChirality =
false,
815 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
816 const boost::dynamic_bitset<> *bondsInPlay =
nullptr);
#define PRECONDITION(expr, mess)
Defines the primary molecule class ROMol as well as associated typedefs.
The class for representing atoms.
int getAtomicNum() const
returns our atomic number
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
std::vector< bondholder > bonds
std::vector< int > revistedNeighbors
std::vector< int > neighborNum
unsigned int getNumAtoms() const
returns our number of atoms
CXXAtomIterator< const MolGraph, Atom *const, MolGraph::adjacency_iterator > atomNeighbors(Atom const *at) const
#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)
void freeCanonAtoms(std::vector< Canon::canon_atom > &atoms)
RDKIT_GRAPHMOL_EXPORT void updateAtomNeighborNumSwaps(canon_atom *atoms, std::vector< bondholder > &nbrs, unsigned int atomIdx, std::vector< std::pair< unsigned int, unsigned int >> &result)
RDKIT_GRAPHMOL_EXPORT void CreateSinglePartition(unsigned int nAtoms, int *order, int *count, canon_atom *atoms)
RDKIT_GRAPHMOL_EXPORT void initCanonAtoms(const ROMol &mol, std::vector< Canon::canon_atom > &atoms, bool includeChirality=true)
RDKIT_GRAPHMOL_EXPORT void ActivatePartitions(unsigned int nAtoms, int *order, int *count, int &activeset, int *next, int *changed)
const unsigned int ATNUM_CLASS_OFFSET
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 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)
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)
RDKIT_GRAPHMOL_EXPORT void rankMolAtoms(const ROMol &mol, std::vector< unsigned int > &res, bool breakTies=true, bool includeChirality=true, bool includeIsotopes=true)
RDKIT_RDGENERAL_EXPORT const std::string _CIPCode
RDKIT_RDGENERAL_EXPORT const std::string molAtomMapNumber
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)