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) {
170 std::vector<std::pair<unsigned int, unsigned int>> swapsi;
171 std::vector<std::pair<unsigned int, unsigned int>> swapsj;
172 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
175 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
178 for (
unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) {
179 int cmp = swapsi[ii].second - swapsj[ii].second;
190 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
191 *dp_bondsInPlay{
nullptr};
196 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
197 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
200 dp_atomsInPlay(atomsInPlay),
201 dp_bondsInPlay(bondsInPlay) {}
206 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
210 if (dp_atoms[i].neighborNum < dp_atoms[j].neighborNum) {
212 }
else if (dp_atoms[i].neighborNum > dp_atoms[j].neighborNum) {
216 if (dp_atoms[i].revistedNeighbors < dp_atoms[j].revistedNeighbors) {
218 }
else if (dp_atoms[i].revistedNeighbors > dp_atoms[j].revistedNeighbors) {
222 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
225 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
228 for (
unsigned int ii = 0;
229 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
235 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
237 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
245 unsigned int getAtomRingNbrCode(
unsigned int i)
const {
246 if (!dp_atoms[i].hasRingNbr)
return 0;
248 int *nbrs = dp_atoms[i].nbrIds;
249 unsigned int code = 0;
250 for (
unsigned j = 0; j < dp_atoms[i].degree; ++j) {
251 if (dp_atoms[nbrs[j]].isRingStereoAtom) {
252 code += dp_atoms[nbrs[j]].index * 10000 + 1;
258 int basecomp(
int i,
int j)
const {
260 unsigned int ivi, ivj;
263 ivi = dp_atoms[i].index;
264 ivj = dp_atoms[j].index;
267 }
else if (ivi > ivj) {
275 int molAtomMapNumber_i = 0;
276 int molAtomMapNumber_j = 0;
281 if (molAtomMapNumber_i < molAtomMapNumber_j) {
283 }
else if (molAtomMapNumber_i > molAtomMapNumber_j) {
287 ivi = dp_atoms[i].degree;
288 ivj = dp_atoms[j].degree;
291 }
else if (ivi > ivj) {
294 if (dp_atoms[i].p_symbol && dp_atoms[j].p_symbol) {
295 if (*(dp_atoms[i].p_symbol) < *(dp_atoms[j].p_symbol)) {
297 }
else if (*(dp_atoms[i].p_symbol) > *(dp_atoms[j].p_symbol)) {
305 ivi = dp_atoms[i].atom->getAtomicNum();
306 ivj = dp_atoms[j].atom->getAtomicNum();
309 }
else if (ivi > ivj) {
313 if (df_useIsotopes) {
314 ivi = dp_atoms[i].atom->getIsotope();
315 ivj = dp_atoms[j].atom->getIsotope();
318 }
else if (ivi > ivj) {
324 ivi = dp_atoms[i].totalNumHs;
325 ivj = dp_atoms[j].totalNumHs;
328 }
else if (ivi > ivj) {
332 ivi = dp_atoms[i].atom->getFormalCharge();
333 ivj = dp_atoms[j].atom->getFormalCharge();
336 }
else if (ivi > ivj) {
340 if (df_useChirality) {
347 ivi = cipCode ==
"R" ? 2 : 1;
351 ivj = cipCode ==
"R" ? 2 : 1;
355 }
else if (ivi > ivj) {
359 ivi = dp_atoms[i].atom->getChiralTag() != 0;
360 ivj = dp_atoms[j].atom->getChiralTag() != 0;
363 }
else if (ivi > ivj) {
368 if (df_useChiralityRings) {
370 ivi = getAtomRingNbrCode(i);
371 ivj = getAtomRingNbrCode(j);
374 }
else if (ivi > ivj) {
384 const boost::dynamic_bitset<> *dp_atomsInPlay{
nullptr},
385 *dp_bondsInPlay{
nullptr};
386 bool df_useNbrs{
false};
387 bool df_useIsotopes{
true};
388 bool df_useChirality{
true};
389 bool df_useChiralityRings{
true};
393 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
394 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
397 dp_atomsInPlay(atomsInPlay),
398 dp_bondsInPlay(bondsInPlay),
400 df_useIsotopes(true),
401 df_useChirality(true),
402 df_useChiralityRings(true) {}
407 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
410 int v = basecomp(i, j);
416 if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
419 if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
423 for (
unsigned int ii = 0;
424 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
433 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
435 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
450 void getAtomNeighborhood(std::vector<bondholder> &nbrs)
const {
451 for (
unsigned j = 0; j < nbrs.size(); ++j) {
452 unsigned int nbrIdx = nbrs[j].nbrIdx;
457 const Atom *nbr = dp_atoms[nbrIdx].atom;
458 nbrs[j].nbrSymClass =
465 int basecomp(
int i,
int j)
const {
467 unsigned int ivi, ivj;
470 ivi = dp_atoms[i].index;
471 ivj = dp_atoms[j].index;
478 ivi = dp_atoms[i].atom->getAtomicNum();
479 ivj = dp_atoms[j].atom->getAtomicNum();
486 ivi = dp_atoms[i].atom->getIsotope();
487 ivj = dp_atoms[j].atom->getIsotope();
499 ivi = cipCode ==
"R" ? 2 : 1;
503 ivj = cipCode ==
"R" ? 2 : 1;
517 bool df_useNbrs{
false};
520 : dp_atoms(atoms), dp_mol(&m), df_useNbrs(false) {}
525 int v = basecomp(i, j);
529 getAtomNeighborhood(dp_atoms[i].bonds);
530 getAtomNeighborhood(dp_atoms[j].bonds);
535 for (
unsigned int ii = 0;
536 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
542 for (
unsigned int ii = 0;
543 ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
549 if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
551 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
564 template <
typename CompareFunc>
566 int mode,
int *order,
int *count,
int &activeset,
567 int *next,
int *changed,
char *touchedPartitions) {
579 while (activeset != -1) {
591 partition = activeset;
592 activeset = next[partition];
593 next[partition] = -2;
595 len = count[partition];
596 offset = atoms[partition].
index;
597 start = order + offset;
608 hanoisort(start, len, count, changed, compar);
615 for (
int k = 0; k < len; ++k) {
616 changed[start[k]] = 0;
622 for (i = count[index]; i < len; i++) {
624 if (count[index]) symclass = offset + i;
625 atoms[index].
index = symclass;
630 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
631 changed[atoms[index].
nbrIds[j]] = 1;
638 for (i = count[index]; i < len; i++) {
640 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
641 unsigned int nbor = atoms[index].
nbrIds[j];
642 touchedPartitions[atoms[nbor].
index] = 1;
645 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
646 if (touchedPartitions[ii]) {
647 partition = order[ii];
648 if ((count[partition] > 1) && (next[partition] == -2)) {
649 next[partition] = activeset;
650 activeset = partition;
652 touchedPartitions[ii] = 0;
659 template <
typename CompareFunc>
661 int mode,
int *order,
int *count,
int &activeset,
int *next,
662 int *changed,
char *touchedPartitions) {
670 for (
unsigned int i = 0; i < nAtoms; i++) {
671 partition = order[i];
672 oldPart = atoms[partition].
index;
673 while (count[partition] > 1) {
674 len = count[partition];
675 offset = atoms[partition].
index + len - 1;
676 index = order[offset];
677 atoms[index].
index = offset;
678 count[partition] = len - 1;
682 if (atoms[index].degree < 1) {
685 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
686 unsigned int nbor = atoms[index].
nbrIds[j];
687 touchedPartitions[atoms[nbor].
index] = 1;
691 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
692 if (touchedPartitions[ii]) {
693 int npart = order[ii];
694 if ((count[npart] > 1) && (next[npart] == -2)) {
695 next[npart] = activeset;
698 touchedPartitions[ii] = 0;
702 changed, touchedPartitions);
705 if (atoms[partition].index != oldPart) {
712 int *order,
int *count,
716 int *count,
int &activeset,
717 int *next,
int *changed);
720 std::vector<unsigned int> &res,
721 bool breakTies =
true,
722 bool includeChirality =
true,
723 bool includeIsotopes =
true);
726 const ROMol &mol, std::vector<unsigned int> &res,
727 const boost::dynamic_bitset<> &atomsInPlay,
728 const boost::dynamic_bitset<> &bondsInPlay,
729 const std::vector<std::string> *atomSymbols,
730 const std::vector<std::string> *bondSymbols,
bool breakTies,
731 bool includeChirality,
bool includeIsotope);
734 const ROMol &mol, std::vector<unsigned int> &res,
735 const boost::dynamic_bitset<> &atomsInPlay,
736 const boost::dynamic_bitset<> &bondsInPlay,
737 const std::vector<std::string> *atomSymbols =
nullptr,
738 bool breakTies =
true,
bool includeChirality =
true,
739 bool includeIsotopes =
true) {
741 breakTies, includeChirality, includeIsotopes);
745 std::vector<unsigned int> &res);
748 std::vector<Canon::canon_atom> &atoms,
749 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)