18#include <boost/dynamic_bitset.hpp>
34 unsigned int nbrSymClass{0};
35 unsigned int nbrIdx{0};
36 const std::string *p_symbol{
42 bondStereo(static_cast<unsigned int>(bs)),
47 : bondType(bt), bondStereo(bs), nbrSymClass(nsc), nbrIdx(ni) {}
74 unsigned int div = 1) {
99 unsigned int degree{0};
100 unsigned int totalNumHs{0};
101 bool hasRingNbr{
false};
102 bool isRingStereoAtom{
false};
103 int *nbrIds{
nullptr};
104 const std::string *p_symbol{
116 canon_atom *atoms, std::vector<bondholder> &nbrs);
119 canon_atom *atoms, std::vector<bondholder> &nbrs,
unsigned int atomIdx,
120 std::vector<std::pair<unsigned int, unsigned int>> &result);
137 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
138 *dp_bondsInPlay{
nullptr};
143 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
144 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
147 dp_atomsInPlay(atomsInPlay),
148 dp_bondsInPlay(bondsInPlay) {}
153 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
157 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
160 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
163 for (
unsigned int ii = 0;
164 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
172 std::vector<std::pair<unsigned int, unsigned int>> swapsi;
173 std::vector<std::pair<unsigned int, unsigned int>> swapsj;
174 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
177 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
180 for (
unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) {
181 int cmp = swapsi[ii].second - swapsj[ii].second;
194 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
195 *dp_bondsInPlay{
nullptr};
200 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
201 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
204 dp_atomsInPlay(atomsInPlay),
205 dp_bondsInPlay(bondsInPlay) {}
210 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
214 if (dp_atoms[i].neighborNum < dp_atoms[j].neighborNum) {
216 }
else if (dp_atoms[i].neighborNum > dp_atoms[j].neighborNum) {
220 if (dp_atoms[i].revistedNeighbors < dp_atoms[j].revistedNeighbors) {
222 }
else if (dp_atoms[i].revistedNeighbors > dp_atoms[j].revistedNeighbors) {
226 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
229 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
232 for (
unsigned int ii = 0;
233 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
241 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
243 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
251 unsigned int getAtomRingNbrCode(
unsigned int i)
const {
252 if (!dp_atoms[i].hasRingNbr) {
256 int *nbrs = dp_atoms[i].nbrIds;
257 unsigned int code = 0;
258 for (
unsigned j = 0; j < dp_atoms[i].degree; ++j) {
259 if (dp_atoms[nbrs[j]].isRingStereoAtom) {
260 code += dp_atoms[nbrs[j]].index * 10000 + 1;
266 int basecomp(
int i,
int j)
const {
268 unsigned int ivi, ivj;
271 ivi = dp_atoms[i].index;
272 ivj = dp_atoms[j].index;
275 }
else if (ivi > ivj) {
283 int molAtomMapNumber_i = 0;
284 int molAtomMapNumber_j = 0;
289 if (molAtomMapNumber_i < molAtomMapNumber_j) {
291 }
else if (molAtomMapNumber_i > molAtomMapNumber_j) {
295 ivi = dp_atoms[i].degree;
296 ivj = dp_atoms[j].degree;
299 }
else if (ivi > ivj) {
302 if (dp_atoms[i].p_symbol && dp_atoms[j].p_symbol) {
303 if (*(dp_atoms[i].p_symbol) < *(dp_atoms[j].p_symbol)) {
305 }
else if (*(dp_atoms[i].p_symbol) > *(dp_atoms[j].p_symbol)) {
313 ivi = dp_atoms[i].atom->getAtomicNum();
314 ivj = dp_atoms[j].atom->getAtomicNum();
317 }
else if (ivi > ivj) {
321 if (df_useIsotopes) {
322 ivi = dp_atoms[i].atom->getIsotope();
323 ivj = dp_atoms[j].atom->getIsotope();
326 }
else if (ivi > ivj) {
332 ivi = dp_atoms[i].totalNumHs;
333 ivj = dp_atoms[j].totalNumHs;
336 }
else if (ivi > ivj) {
340 ivi = dp_atoms[i].atom->getFormalCharge();
341 ivj = dp_atoms[j].atom->getFormalCharge();
344 }
else if (ivi > ivj) {
348 if (df_useChirality) {
355 ivi = cipCode ==
"R" ? 2 : 1;
359 ivj = cipCode ==
"R" ? 2 : 1;
363 }
else if (ivi > ivj) {
367 ivi = dp_atoms[i].atom->getChiralTag() != 0;
368 ivj = dp_atoms[j].atom->getChiralTag() != 0;
371 }
else if (ivi > ivj) {
376 if (df_useChiralityRings) {
378 ivi = getAtomRingNbrCode(i);
379 ivj = getAtomRingNbrCode(j);
382 }
else if (ivi > ivj) {
392 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
393 *dp_bondsInPlay{
nullptr};
394 bool df_useNbrs{
false};
395 bool df_useIsotopes{
true};
396 bool df_useChirality{
true};
397 bool df_useChiralityRings{
true};
401 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
402 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
405 dp_atomsInPlay(atomsInPlay),
406 dp_bondsInPlay(bondsInPlay),
408 df_useIsotopes(true),
409 df_useChirality(true),
410 df_useChiralityRings(true) {}
415 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
418 int v = basecomp(i, j);
424 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
427 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
431 for (
unsigned int ii = 0;
432 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
441 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
443 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
458 void getAtomNeighborhood(std::vector<bondholder> &nbrs)
const {
459 for (
unsigned j = 0; j < nbrs.size(); ++j) {
460 unsigned int nbrIdx = nbrs[j].nbrIdx;
465 const Atom *nbr = dp_atoms[nbrIdx].atom;
466 nbrs[j].nbrSymClass =
473 int basecomp(
int i,
int j)
const {
475 unsigned int ivi, ivj;
478 ivi = dp_atoms[i].index;
479 ivj = dp_atoms[j].index;
482 }
else if (ivi > ivj) {
487 ivi = dp_atoms[i].atom->getAtomicNum();
488 ivj = dp_atoms[j].atom->getAtomicNum();
491 }
else if (ivi > ivj) {
496 ivi = dp_atoms[i].atom->getIsotope();
497 ivj = dp_atoms[j].atom->getIsotope();
500 }
else if (ivi > ivj) {
510 ivi = cipCode ==
"R" ? 2 : 1;
514 ivj = cipCode ==
"R" ? 2 : 1;
518 }
else if (ivi > ivj) {
529 bool df_useNbrs{
false};
532 : dp_atoms(atoms), dp_mol(&m), df_useNbrs(false) {}
537 int v = basecomp(i, j);
543 getAtomNeighborhood(dp_atoms[i].bonds);
544 getAtomNeighborhood(dp_atoms[j].bonds);
549 for (
unsigned int ii = 0;
550 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
558 for (
unsigned int ii = 0;
559 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
567 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
569 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
582template <
typename CompareFunc>
584 int mode,
int *order,
int *count,
int &activeset,
585 int *next,
int *changed,
char *touchedPartitions) {
597 while (activeset != -1) {
609 partition = activeset;
610 activeset = next[partition];
611 next[partition] = -2;
613 len = count[partition];
614 offset = atoms[partition].
index;
615 start = order + offset;
626 hanoisort(start, len, count, changed, compar);
633 for (
int k = 0; k < len; ++k) {
634 changed[start[k]] = 0;
640 for (i = count[index]; i < len; i++) {
643 symclass = offset + i;
645 atoms[index].
index = symclass;
650 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
651 changed[atoms[index].
nbrIds[j]] = 1;
658 for (i = count[index]; i < len; i++) {
660 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
661 unsigned int nbor = atoms[index].
nbrIds[j];
662 touchedPartitions[atoms[nbor].
index] = 1;
665 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
666 if (touchedPartitions[ii]) {
667 partition = order[ii];
668 if ((count[partition] > 1) && (next[partition] == -2)) {
669 next[partition] = activeset;
670 activeset = partition;
672 touchedPartitions[ii] = 0;
679template <
typename CompareFunc>
681 int mode,
int *order,
int *count,
int &activeset,
int *next,
682 int *changed,
char *touchedPartitions) {
690 for (
unsigned int i = 0; i < nAtoms; i++) {
691 partition = order[i];
692 oldPart = atoms[partition].
index;
693 while (count[partition] > 1) {
694 len = count[partition];
695 offset = atoms[partition].
index + len - 1;
696 index = order[offset];
697 atoms[index].
index = offset;
698 count[partition] = len - 1;
702 if (atoms[index].degree < 1) {
705 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
706 unsigned int nbor = atoms[index].
nbrIds[j];
707 touchedPartitions[atoms[nbor].
index] = 1;
711 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
712 if (touchedPartitions[ii]) {
713 int npart = order[ii];
714 if ((count[npart] > 1) && (next[npart] == -2)) {
715 next[npart] = activeset;
718 touchedPartitions[ii] = 0;
722 changed, touchedPartitions);
725 if (atoms[partition].index != oldPart) {
732 int *order,
int *count,
736 int *count,
int &activeset,
737 int *next,
int *changed);
740 std::vector<unsigned int> &res,
741 bool breakTies =
true,
742 bool includeChirality =
true,
743 bool includeIsotopes =
true);
746 const ROMol &mol, std::vector<unsigned int> &res,
747 const boost::dynamic_bitset<> &atomsInPlay,
748 const boost::dynamic_bitset<> &bondsInPlay,
749 const std::vector<std::string> *atomSymbols,
750 const std::vector<std::string> *bondSymbols,
bool breakTies,
751 bool includeChirality,
bool includeIsotope);
754 const ROMol &mol, std::vector<unsigned int> &res,
755 const boost::dynamic_bitset<> &atomsInPlay,
756 const boost::dynamic_bitset<> &bondsInPlay,
757 const std::vector<std::string> *atomSymbols =
nullptr,
758 bool breakTies =
true,
bool includeChirality =
true,
759 bool includeIsotopes =
true) {
761 breakTies, includeChirality, includeIsotopes);
765 std::vector<unsigned int> &res);
768 std::vector<Canon::canon_atom> &atoms,
769 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 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
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 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)