15 #include <boost/cstdint.hpp> 16 #include <boost/foreach.hpp> 17 #include <boost/dynamic_bitset.hpp> 35 : bondType(
Bond::UNSPECIFIED),
36 bondStereo(static_cast<unsigned int>(
Bond::STEREONONE)),
42 bondStereo(static_cast<unsigned int>(bs)),
47 : bondType(bt), bondStereo(bs), nbrSymClass(nsc), nbrIdx(ni){};
61 unsigned int div = 1) {
93 isRingStereoAtom(false),
101 canon_atom *atoms, std::vector<bondholder> &nbrs,
unsigned int atomIdx,
102 std::vector<std::pair<unsigned int, unsigned int> > &result);
124 dp_atomsInPlay(NULL),
125 dp_bondsInPlay(NULL){};
128 const boost::dynamic_bitset<> *atomsInPlay = NULL,
129 const boost::dynamic_bitset<> *bondsInPlay = NULL)
132 dp_atomsInPlay(atomsInPlay),
133 dp_bondsInPlay(bondsInPlay){};
138 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
142 if ((dp_atomsInPlay && (*dp_atomsInPlay)[i]) || !dp_atomsInPlay) {
145 if ((dp_atomsInPlay && (*dp_atomsInPlay)[j]) || !dp_atomsInPlay) {
148 for (
unsigned int ii = 0;
149 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].
bonds.size(); ++ii) {
155 std::vector<std::pair<unsigned int, unsigned int> > swapsi;
156 std::vector<std::pair<unsigned int, unsigned int> > swapsj;
157 if ((dp_atomsInPlay && (*dp_atomsInPlay)[i]) || !dp_atomsInPlay) {
160 if ((dp_atomsInPlay && (*dp_atomsInPlay)[j]) || !dp_atomsInPlay) {
163 for (
unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) {
164 int cmp = swapsi[ii].second - swapsj[ii].second;
180 dp_atomsInPlay(NULL),
181 dp_bondsInPlay(NULL){};
184 const boost::dynamic_bitset<> *atomsInPlay = NULL,
185 const boost::dynamic_bitset<> *bondsInPlay = NULL)
188 dp_atomsInPlay(atomsInPlay),
189 dp_bondsInPlay(bondsInPlay){};
194 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
198 if (dp_atoms[i].neighborNum < dp_atoms[j].neighborNum) {
200 }
else if (dp_atoms[i].neighborNum > dp_atoms[j].neighborNum) {
204 if (dp_atoms[i].revistedNeighbors < dp_atoms[j].revistedNeighbors) {
206 }
else if (dp_atoms[i].revistedNeighbors > dp_atoms[j].revistedNeighbors) {
210 if ((dp_atomsInPlay && (*dp_atomsInPlay)[i]) || !dp_atomsInPlay) {
213 if ((dp_atomsInPlay && (*dp_atomsInPlay)[j]) || !dp_atomsInPlay) {
216 for (
unsigned int ii = 0;
217 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].
bonds.size(); ++ii) {
223 if (dp_atoms[i].bonds.size() < dp_atoms[j].
bonds.size()) {
225 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].
bonds.size()) {
233 unsigned int getAtomRingNbrCode(
unsigned int i)
const {
234 if (!dp_atoms[i].hasRingNbr)
return 0;
236 int *nbrs = dp_atoms[i].nbrIds;
237 unsigned int code = 0;
238 for (
unsigned j = 0; j < dp_atoms[i].degree; ++j) {
239 if (dp_atoms[nbrs[j]].isRingStereoAtom) {
240 code += dp_atoms[nbrs[j]].index * 10000 + 1;
246 int basecomp(
int i,
int j)
const {
248 unsigned int ivi, ivj;
251 ivi = dp_atoms[i].index;
252 ivj = dp_atoms[j].index;
263 int molAtomMapNumber_i = 0;
264 int molAtomMapNumber_j = 0;
269 if (molAtomMapNumber_i < molAtomMapNumber_j)
271 else if (molAtomMapNumber_i > molAtomMapNumber_j)
275 ivi = dp_atoms[i].degree;
276 ivj = dp_atoms[j].degree;
282 if (dp_atoms[i].p_symbol && dp_atoms[j].p_symbol) {
283 if (*(dp_atoms[i].p_symbol) < *(dp_atoms[j].p_symbol))
285 else if (*(dp_atoms[i].p_symbol) > *(dp_atoms[j].p_symbol))
291 ivi = dp_atoms[i].atom->getAtomicNum();
292 ivj = dp_atoms[j].atom->getAtomicNum();
299 if (df_useIsotopes) {
300 ivi = dp_atoms[i].atom->getIsotope();
301 ivj = dp_atoms[j].atom->getIsotope();
309 ivi = dp_atoms[i].totalNumHs;
310 ivj = dp_atoms[j].totalNumHs;
317 ivi = dp_atoms[i].atom->getFormalCharge();
318 ivj = dp_atoms[j].atom->getFormalCharge();
325 if (df_useChirality) {
332 ivi = cipCode ==
"R" ? 2 : 1;
336 ivj = cipCode ==
"R" ? 2 : 1;
344 ivi = dp_atoms[i].atom->getChiralTag() != 0;
345 ivj = dp_atoms[j].atom->getChiralTag() != 0;
351 if (df_useChiralityRings) {
353 ivi = getAtomRingNbrCode(i);
354 ivj = getAtomRingNbrCode(j);
376 dp_atomsInPlay(NULL),
377 dp_bondsInPlay(NULL),
379 df_useIsotopes(true),
380 df_useChirality(true),
381 df_useChiralityRings(true){};
383 const boost::dynamic_bitset<> *atomsInPlay = NULL,
384 const boost::dynamic_bitset<> *bondsInPlay = NULL)
387 dp_atomsInPlay(atomsInPlay),
388 dp_bondsInPlay(bondsInPlay),
390 df_useIsotopes(true),
391 df_useChirality(true),
392 df_useChiralityRings(true){};
397 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
401 int v = basecomp(i, j);
407 if ((dp_atomsInPlay && (*dp_atomsInPlay)[i]) || !dp_atomsInPlay) {
410 if ((dp_atomsInPlay && (*dp_atomsInPlay)[j]) || !dp_atomsInPlay) {
414 for (
unsigned int ii = 0;
415 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].
bonds.size();
422 if (dp_atoms[i].bonds.size() < dp_atoms[j].
bonds.size()) {
424 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].
bonds.size()) {
439 void getAtomNeighborhood(std::vector<bondholder> &nbrs)
const {
440 for (
unsigned j = 0; j < nbrs.size(); ++j) {
441 unsigned int nbrIdx = nbrs[j].nbrIdx;
442 if (nbrIdx == ATNUM_CLASS_OFFSET) {
447 nbrs[j].nbrSymClass =
454 int basecomp(
int i,
int j)
const {
456 unsigned int ivi, ivj;
459 ivi = dp_atoms[i].index;
460 ivj = dp_atoms[j].index;
467 ivi = dp_atoms[i].atom->getAtomicNum();
468 ivj = dp_atoms[j].atom->getAtomicNum();
475 ivi = dp_atoms[i].atom->getIsotope();
476 ivj = dp_atoms[j].atom->getIsotope();
488 ivi = cipCode ==
"R" ? 2 : 1;
492 ivj = cipCode ==
"R" ? 2 : 1;
508 : dp_atoms(NULL), dp_mol(NULL), df_useNbrs(false){};
510 : dp_atoms(atoms), dp_mol(&m), df_useNbrs(false){};
515 int v = basecomp(i, j);
519 getAtomNeighborhood(dp_atoms[i].bonds);
520 getAtomNeighborhood(dp_atoms[j].bonds);
525 for (
unsigned int ii = 0;
526 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].
bonds.size();
529 dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii], ATNUM_CLASS_OFFSET);
532 for (
unsigned int ii = 0;
533 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].
bonds.size();
539 if (dp_atoms[i].bonds.size() < dp_atoms[j].
bonds.size()) {
541 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].
bonds.size()) {
554 template <
typename CompareFunc>
556 int mode,
int *order,
int *count,
int &activeset,
557 int *next,
int *changed,
char *touchedPartitions) {
569 while (activeset != -1) {
581 partition = activeset;
582 activeset = next[partition];
583 next[partition] = -2;
585 len = count[partition];
586 offset = atoms[partition].
index;
587 start = order + offset;
598 hanoisort(start, len, count, changed, compar);
605 for (
int k = 0; k < len; ++k) {
606 changed[start[k]] = 0;
612 for (i = count[index]; i < len; i++) {
614 if (count[index]) symclass = offset + i;
615 atoms[index].
index = symclass;
620 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
621 changed[atoms[index].
nbrIds[j]] = 1;
628 for (i = count[index]; i < len; i++) {
630 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
631 unsigned int nbor = atoms[index].
nbrIds[j];
632 touchedPartitions[atoms[nbor].
index] = 1;
635 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
636 if (touchedPartitions[ii]) {
637 partition = order[ii];
638 if ((count[partition] > 1) && (next[partition] == -2)) {
639 next[partition] = activeset;
640 activeset = partition;
642 touchedPartitions[ii] = 0;
649 template <
typename CompareFunc>
651 int mode,
int *order,
int *count,
int &activeset,
int *next,
652 int *changed,
char *touchedPartitions) {
660 for (
unsigned int i = 0; i < nAtoms; i++) {
661 partition = order[i];
662 oldPart = atoms[partition].
index;
663 while (count[partition] > 1) {
664 len = count[partition];
665 offset = atoms[partition].
index + len - 1;
666 index = order[offset];
667 atoms[index].
index = offset;
668 count[partition] = len - 1;
672 if (atoms[index].degree < 1) {
675 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
676 unsigned int nbor = atoms[index].
nbrIds[j];
677 touchedPartitions[atoms[nbor].
index] = 1;
681 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
682 if (touchedPartitions[ii]) {
683 int npart = order[ii];
684 if ((count[npart] > 1) && (next[npart] == -2)) {
685 next[npart] = activeset;
688 touchedPartitions[ii] = 0;
692 changed, touchedPartitions);
695 if (atoms[partition].index != oldPart) {
705 int &activeset,
int *next,
int *changed);
708 bool breakTies =
true,
bool includeChirality =
true,
709 bool includeIsotopes =
true);
712 const boost::dynamic_bitset<> &atomsInPlay,
713 const boost::dynamic_bitset<> &bondsInPlay,
714 const std::vector<std::string> *atomSymbols = NULL,
715 bool breakTies =
true,
bool includeChirality =
true,
716 bool includeIsotopes =
true);
721 bool includeChirality =
true);
bool operator<(const bondholder &o) const
const std::string * p_symbol
void chiralRankMolAtoms(const ROMol &mol, std::vector< unsigned int > &res)
SpecialSymmetryAtomCompareFunctor()
const boost::dynamic_bitset * dp_bondsInPlay
int operator()(int i, int j) const
std::vector< int > neighborNum
unsigned int getNumAtoms(bool onlyExplicit=1) const
returns our number of atoms
void rankMolAtoms(const ROMol &mol, std::vector< unsigned int > &res, bool breakTies=true, bool includeChirality=true, bool includeIsotopes=true)
void updateAtomNeighborIndex(canon_atom *atoms, std::vector< bondholder > &nbrs)
void CreateSinglePartition(unsigned int nAtoms, int *order, int *count, canon_atom *atoms)
void ActivatePartitions(unsigned int nAtoms, int *order, int *count, int &activeset, int *next, int *changed)
const std::string molAtomMapNumber
Defines the primary molecule class ROMol as well as associated typedefs.
void hanoisort(int *base, int nel, int *count, int *changed, CompareFunc compar)
bool df_useChiralityRings
BondStereo
the nature of the bond's stereochem (for cis/trans)
Canon::canon_atom * dp_atoms
AtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=NULL, const boost::dynamic_bitset<> *bondsInPlay=NULL)
bondholder(Bond::BondType bt, Bond::BondStereo bs, unsigned int ni, unsigned int nsc)
ROMol is a molecule class that is intended to have a fixed topology.
int operator()(int i, int j) const
const boost::dynamic_bitset * dp_bondsInPlay
std::vector< bondholder > bonds
static bool greater(const bondholder &lhs, const bondholder &rhs)
int operator()(int i, int j) const
ChiralAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m)
const unsigned int ATNUM_CLASS_OFFSET
Canon::canon_atom * dp_atoms
SpecialSymmetryAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=NULL, const boost::dynamic_bitset<> *bondsInPlay=NULL)
ChiralAtomCompareFunctor()
int operator()(int i, int j) const
const std::string _CIPCode
Includes a bunch of functionality for handling Atom and Bond queries.
int getAtomicNum() const
returns our atomic number
void BreakTies(const ROMol &mol, canon_atom *atoms, CompareFunc compar, int mode, int *order, int *count, int &activeset, int *next, int *changed, char *touchedPartitions)
Canon::canon_atom * dp_atoms
const boost::dynamic_bitset * dp_bondsInPlay
class for representing a bond
SpecialChiralityAtomCompareFunctor()
static int compare(const bondholder &x, const bondholder &y, unsigned int div=1)
void RefinePartitions(const ROMol &mol, canon_atom *atoms, CompareFunc compar, int mode, int *order, int *count, int &activeset, int *next, int *changed, char *touchedPartitions)
#define PRECONDITION(expr, mess)
void updateAtomNeighborNumSwaps(canon_atom *atoms, std::vector< bondholder > &nbrs, unsigned int atomIdx, std::vector< std::pair< unsigned int, unsigned int > > &result)
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=NULL, bool breakTies=true, bool includeChirality=true, bool includeIsotopes=true)
std::vector< int > revistedNeighbors
bondholder(Bond::BondType bt, unsigned int bs, unsigned int ni, unsigned int nsc)
void initCanonAtoms(const ROMol &mol, std::vector< Canon::canon_atom > &atoms, bool includeChirality=true)
SpecialChiralityAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=NULL, const boost::dynamic_bitset<> *bondsInPlay=NULL)
The class for representing atoms.
Canon::canon_atom * dp_atoms