18 #include <boost/foreach.hpp>
19 #include <boost/dynamic_bitset.hpp>
35 unsigned int nbrSymClass{0};
36 unsigned int nbrIdx{0};
37 const std::string *p_symbol{
43 bondStereo(static_cast<unsigned int>(bs)),
48 : bondType(bt), bondStereo(bs), nbrSymClass(nsc), nbrIdx(ni){};
75 unsigned int div = 1) {
100 unsigned int degree{0};
101 unsigned int totalNumHs{0};
102 bool hasRingNbr{
false};
103 bool isRingStereoAtom{
false};
104 int *nbrIds{
nullptr};
105 const std::string *p_symbol{
117 canon_atom *atoms, std::vector<bondholder> &nbrs);
120 canon_atom *atoms, std::vector<bondholder> &nbrs,
unsigned int atomIdx,
121 std::vector<std::pair<unsigned int, unsigned int>> &result);
138 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
139 *dp_bondsInPlay{
nullptr};
146 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
147 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
150 dp_atomsInPlay(atomsInPlay),
151 dp_bondsInPlay(bondsInPlay){};
156 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
160 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
163 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
166 for (
unsigned int ii = 0;
167 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
173 std::vector<std::pair<unsigned int, unsigned int>> swapsi;
174 std::vector<std::pair<unsigned int, unsigned int>> swapsj;
175 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
178 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
181 for (
unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) {
182 int cmp = swapsi[ii].second - swapsj[ii].second;
193 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
194 *dp_bondsInPlay{
nullptr};
201 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
202 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
205 dp_atomsInPlay(atomsInPlay),
206 dp_bondsInPlay(bondsInPlay){};
211 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
215 if (dp_atoms[i].neighborNum < dp_atoms[j].neighborNum) {
217 }
else if (dp_atoms[i].neighborNum > dp_atoms[j].neighborNum) {
221 if (dp_atoms[i].revistedNeighbors < dp_atoms[j].revistedNeighbors) {
223 }
else if (dp_atoms[i].revistedNeighbors > dp_atoms[j].revistedNeighbors) {
227 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
230 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
233 for (
unsigned int ii = 0;
234 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
240 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
242 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
250 unsigned int getAtomRingNbrCode(
unsigned int i)
const {
251 if (!dp_atoms[i].hasRingNbr)
return 0;
253 int *nbrs = dp_atoms[i].nbrIds;
254 unsigned int code = 0;
255 for (
unsigned j = 0; j < dp_atoms[i].degree; ++j) {
256 if (dp_atoms[nbrs[j]].isRingStereoAtom) {
257 code += dp_atoms[nbrs[j]].index * 10000 + 1;
263 int basecomp(
int i,
int j)
const {
265 unsigned int ivi, ivj;
268 ivi = dp_atoms[i].index;
269 ivj = dp_atoms[j].index;
272 }
else if (ivi > ivj) {
280 int molAtomMapNumber_i = 0;
281 int molAtomMapNumber_j = 0;
286 if (molAtomMapNumber_i < molAtomMapNumber_j) {
288 }
else if (molAtomMapNumber_i > molAtomMapNumber_j) {
292 ivi = dp_atoms[i].degree;
293 ivj = dp_atoms[j].degree;
296 }
else if (ivi > ivj) {
299 if (dp_atoms[i].p_symbol && dp_atoms[j].p_symbol) {
300 if (*(dp_atoms[i].p_symbol) < *(dp_atoms[j].p_symbol)) {
302 }
else if (*(dp_atoms[i].p_symbol) > *(dp_atoms[j].p_symbol)) {
310 ivi = dp_atoms[i].atom->getAtomicNum();
311 ivj = dp_atoms[j].atom->getAtomicNum();
314 }
else if (ivi > ivj) {
318 if (df_useIsotopes) {
319 ivi = dp_atoms[i].atom->getIsotope();
320 ivj = dp_atoms[j].atom->getIsotope();
323 }
else if (ivi > ivj) {
329 ivi = dp_atoms[i].totalNumHs;
330 ivj = dp_atoms[j].totalNumHs;
333 }
else if (ivi > ivj) {
337 ivi = dp_atoms[i].atom->getFormalCharge();
338 ivj = dp_atoms[j].atom->getFormalCharge();
341 }
else if (ivi > ivj) {
345 if (df_useChirality) {
352 ivi = cipCode ==
"R" ? 2 : 1;
356 ivj = cipCode ==
"R" ? 2 : 1;
360 }
else if (ivi > ivj) {
364 ivi = dp_atoms[i].atom->getChiralTag() != 0;
365 ivj = dp_atoms[j].atom->getChiralTag() != 0;
368 }
else if (ivi > ivj) {
373 if (df_useChiralityRings) {
375 ivi = getAtomRingNbrCode(i);
376 ivj = getAtomRingNbrCode(j);
379 }
else if (ivi > ivj) {
389 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
390 *dp_bondsInPlay{
nullptr};
391 bool df_useNbrs{
false};
392 bool df_useIsotopes{
true};
393 bool df_useChirality{
true};
394 bool df_useChiralityRings{
true};
400 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
401 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
404 dp_atomsInPlay(atomsInPlay),
405 dp_bondsInPlay(bondsInPlay),
407 df_useIsotopes(true),
408 df_useChirality(true),
409 df_useChiralityRings(true){};
414 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
417 int v = basecomp(i, j);
423 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
426 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
430 for (
unsigned int ii = 0;
431 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
440 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
442 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
457 void getAtomNeighborhood(std::vector<bondholder> &nbrs)
const {
458 for (
unsigned j = 0; j < nbrs.size(); ++j) {
459 unsigned int nbrIdx = nbrs[j].nbrIdx;
464 const Atom *nbr = dp_atoms[nbrIdx].atom;
465 nbrs[j].nbrSymClass =
472 int basecomp(
int i,
int j)
const {
474 unsigned int ivi, ivj;
477 ivi = dp_atoms[i].index;
478 ivj = dp_atoms[j].index;
485 ivi = dp_atoms[i].atom->getAtomicNum();
486 ivj = dp_atoms[j].atom->getAtomicNum();
493 ivi = dp_atoms[i].atom->getIsotope();
494 ivj = dp_atoms[j].atom->getIsotope();
506 ivi = cipCode ==
"R" ? 2 : 1;
510 ivj = cipCode ==
"R" ? 2 : 1;
524 bool df_useNbrs{
false};
527 : dp_atoms(atoms), dp_mol(&m), df_useNbrs(false){};
532 int v = basecomp(i, j);
536 getAtomNeighborhood(dp_atoms[i].bonds);
537 getAtomNeighborhood(dp_atoms[j].bonds);
542 for (
unsigned int ii = 0;
543 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
549 for (
unsigned int ii = 0;
550 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
556 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
558 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
571 template <
typename CompareFunc>
573 int mode,
int *order,
int *count,
int &activeset,
574 int *next,
int *changed,
char *touchedPartitions) {
586 while (activeset != -1) {
598 partition = activeset;
599 activeset = next[partition];
600 next[partition] = -2;
602 len = count[partition];
603 offset = atoms[partition].
index;
604 start = order + offset;
615 hanoisort(start, len, count, changed, compar);
622 for (
int k = 0; k < len; ++k) {
623 changed[start[k]] = 0;
629 for (i = count[index]; i < len; i++) {
631 if (count[index]) symclass = offset + i;
632 atoms[index].
index = symclass;
637 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
638 changed[atoms[index].
nbrIds[j]] = 1;
645 for (i = count[index]; i < len; i++) {
647 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
648 unsigned int nbor = atoms[index].
nbrIds[j];
649 touchedPartitions[atoms[nbor].
index] = 1;
652 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
653 if (touchedPartitions[ii]) {
654 partition = order[ii];
655 if ((count[partition] > 1) && (next[partition] == -2)) {
656 next[partition] = activeset;
657 activeset = partition;
659 touchedPartitions[ii] = 0;
666 template <
typename CompareFunc>
668 int mode,
int *order,
int *count,
int &activeset,
int *next,
669 int *changed,
char *touchedPartitions) {
677 for (
unsigned int i = 0; i < nAtoms; i++) {
678 partition = order[i];
679 oldPart = atoms[partition].
index;
680 while (count[partition] > 1) {
681 len = count[partition];
682 offset = atoms[partition].
index + len - 1;
683 index = order[offset];
684 atoms[index].
index = offset;
685 count[partition] = len - 1;
689 if (atoms[index].degree < 1) {
692 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
693 unsigned int nbor = atoms[index].
nbrIds[j];
694 touchedPartitions[atoms[nbor].
index] = 1;
698 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
699 if (touchedPartitions[ii]) {
700 int npart = order[ii];
701 if ((count[npart] > 1) && (next[npart] == -2)) {
702 next[npart] = activeset;
705 touchedPartitions[ii] = 0;
709 changed, touchedPartitions);
712 if (atoms[partition].index != oldPart) {
719 int *order,
int *count,
723 int *count,
int &activeset,
724 int *next,
int *changed);
727 std::vector<unsigned int> &res,
728 bool breakTies =
true,
729 bool includeChirality =
true,
730 bool includeIsotopes =
true);
733 const ROMol &mol, std::vector<unsigned int> &res,
734 const boost::dynamic_bitset<> &atomsInPlay,
735 const boost::dynamic_bitset<> &bondsInPlay,
736 const std::vector<std::string> *atomSymbols,
737 const std::vector<std::string> *bondSymbols,
bool breakTies,
738 bool includeChirality,
bool includeIsotope);
741 const ROMol &mol, std::vector<unsigned int> &res,
742 const boost::dynamic_bitset<> &atomsInPlay,
743 const boost::dynamic_bitset<> &bondsInPlay,
744 const std::vector<std::string> *atomSymbols =
nullptr,
745 bool breakTies =
true,
bool includeChirality =
true,
746 bool includeIsotopes =
true) {
748 breakTies, includeChirality, includeIsotopes);
752 std::vector<unsigned int> &res);
755 std::vector<Canon::canon_atom> &atoms,
756 bool includeChirality =
true);
#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
class for representing a bond
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
#define RDKIT_GRAPHMOL_EXPORT
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)
const std::string * p_symbol
static bool greater(const bondholder &lhs, const bondholder &rhs)
bool operator<(const bondholder &o) const
bondholder(Bond::BondType bt, Bond::BondStereo bs, unsigned int ni, unsigned int nsc)
bondholder(Bond::BondType bt, unsigned int bs, unsigned int ni, unsigned int nsc)
static int compare(const bondholder &x, const bondholder &y, unsigned int div=1)