16 #include <boost/cstdint.hpp> 17 #include <boost/foreach.hpp> 18 #include <boost/dynamic_bitset.hpp> 37 : bondType(
Bond::UNSPECIFIED),
38 bondStereo(static_cast<unsigned int>(
Bond::STEREONONE)),
44 bondStereo(static_cast<unsigned int>(bs)),
49 : bondType(bt), bondStereo(bs), nbrSymClass(nsc), nbrIdx(ni){};
63 unsigned int div = 1) {
95 isRingStereoAtom(false),
103 canon_atom *atoms, std::vector<bondholder> &nbrs,
unsigned int atomIdx,
104 std::vector<std::pair<unsigned int, unsigned int> > &result);
126 dp_atomsInPlay(NULL),
127 dp_bondsInPlay(NULL){};
130 const boost::dynamic_bitset<> *atomsInPlay = NULL,
131 const boost::dynamic_bitset<> *bondsInPlay = NULL)
134 dp_atomsInPlay(atomsInPlay),
135 dp_bondsInPlay(bondsInPlay){};
140 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
144 if ((dp_atomsInPlay && (*dp_atomsInPlay)[i]) || !dp_atomsInPlay) {
147 if ((dp_atomsInPlay && (*dp_atomsInPlay)[j]) || !dp_atomsInPlay) {
150 for (
unsigned int ii = 0;
151 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].
bonds.size(); ++ii) {
157 std::vector<std::pair<unsigned int, unsigned int> > swapsi;
158 std::vector<std::pair<unsigned int, unsigned int> > swapsj;
159 if ((dp_atomsInPlay && (*dp_atomsInPlay)[i]) || !dp_atomsInPlay) {
162 if ((dp_atomsInPlay && (*dp_atomsInPlay)[j]) || !dp_atomsInPlay) {
165 for (
unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) {
166 int cmp = swapsi[ii].second - swapsj[ii].second;
182 dp_atomsInPlay(NULL),
183 dp_bondsInPlay(NULL){};
186 const boost::dynamic_bitset<> *atomsInPlay = NULL,
187 const boost::dynamic_bitset<> *bondsInPlay = NULL)
190 dp_atomsInPlay(atomsInPlay),
191 dp_bondsInPlay(bondsInPlay){};
196 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
200 if (dp_atoms[i].neighborNum < dp_atoms[j].neighborNum) {
202 }
else if (dp_atoms[i].neighborNum > dp_atoms[j].neighborNum) {
206 if (dp_atoms[i].revistedNeighbors < dp_atoms[j].revistedNeighbors) {
208 }
else if (dp_atoms[i].revistedNeighbors > dp_atoms[j].revistedNeighbors) {
212 if ((dp_atomsInPlay && (*dp_atomsInPlay)[i]) || !dp_atomsInPlay) {
215 if ((dp_atomsInPlay && (*dp_atomsInPlay)[j]) || !dp_atomsInPlay) {
218 for (
unsigned int ii = 0;
219 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].
bonds.size(); ++ii) {
225 if (dp_atoms[i].bonds.size() < dp_atoms[j].
bonds.size()) {
227 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].
bonds.size()) {
235 unsigned int getAtomRingNbrCode(
unsigned int i)
const {
236 if (!dp_atoms[i].hasRingNbr)
return 0;
238 int *nbrs = dp_atoms[i].nbrIds;
239 unsigned int code = 0;
240 for (
unsigned j = 0; j < dp_atoms[i].degree; ++j) {
241 if (dp_atoms[nbrs[j]].isRingStereoAtom) {
242 code += dp_atoms[nbrs[j]].index * 10000 + 1;
248 int basecomp(
int i,
int j)
const {
250 unsigned int ivi, ivj;
253 ivi = dp_atoms[i].index;
254 ivj = dp_atoms[j].index;
265 int molAtomMapNumber_i = 0;
266 int molAtomMapNumber_j = 0;
271 if (molAtomMapNumber_i < molAtomMapNumber_j)
273 else if (molAtomMapNumber_i > molAtomMapNumber_j)
277 ivi = dp_atoms[i].degree;
278 ivj = dp_atoms[j].degree;
284 if (dp_atoms[i].p_symbol && dp_atoms[j].p_symbol) {
285 if (*(dp_atoms[i].p_symbol) < *(dp_atoms[j].p_symbol))
287 else if (*(dp_atoms[i].p_symbol) > *(dp_atoms[j].p_symbol))
294 ivi = dp_atoms[i].atom->getAtomicNum();
295 ivj = dp_atoms[j].atom->getAtomicNum();
302 if (df_useIsotopes) {
303 ivi = dp_atoms[i].atom->getIsotope();
304 ivj = dp_atoms[j].atom->getIsotope();
312 ivi = dp_atoms[i].totalNumHs;
313 ivj = dp_atoms[j].totalNumHs;
320 ivi = dp_atoms[i].atom->getFormalCharge();
321 ivj = dp_atoms[j].atom->getFormalCharge();
328 if (df_useChirality) {
335 ivi = cipCode ==
"R" ? 2 : 1;
339 ivj = cipCode ==
"R" ? 2 : 1;
347 ivi = dp_atoms[i].atom->getChiralTag() != 0;
348 ivj = dp_atoms[j].atom->getChiralTag() != 0;
355 if (df_useChiralityRings) {
357 ivi = getAtomRingNbrCode(i);
358 ivj = getAtomRingNbrCode(j);
380 dp_atomsInPlay(NULL),
381 dp_bondsInPlay(NULL),
383 df_useIsotopes(true),
384 df_useChirality(true),
385 df_useChiralityRings(true){};
387 const boost::dynamic_bitset<> *atomsInPlay = NULL,
388 const boost::dynamic_bitset<> *bondsInPlay = NULL)
391 dp_atomsInPlay(atomsInPlay),
392 dp_bondsInPlay(bondsInPlay),
394 df_useIsotopes(true),
395 df_useChirality(true),
396 df_useChiralityRings(true){};
401 if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
405 int v = basecomp(i, j);
411 if ((dp_atomsInPlay && (*dp_atomsInPlay)[i]) || !dp_atomsInPlay) {
414 if ((dp_atomsInPlay && (*dp_atomsInPlay)[j]) || !dp_atomsInPlay) {
418 for (
unsigned int ii = 0;
419 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].
bonds.size();
426 if (dp_atoms[i].bonds.size() < dp_atoms[j].
bonds.size()) {
428 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].
bonds.size()) {
443 void getAtomNeighborhood(std::vector<bondholder> &nbrs)
const {
444 for (
unsigned j = 0; j < nbrs.size(); ++j) {
445 unsigned int nbrIdx = nbrs[j].nbrIdx;
446 if (nbrIdx == ATNUM_CLASS_OFFSET) {
451 nbrs[j].nbrSymClass =
458 int basecomp(
int i,
int j)
const {
460 unsigned int ivi, ivj;
463 ivi = dp_atoms[i].index;
464 ivj = dp_atoms[j].index;
471 ivi = dp_atoms[i].atom->getAtomicNum();
472 ivj = dp_atoms[j].atom->getAtomicNum();
479 ivi = dp_atoms[i].atom->getIsotope();
480 ivj = dp_atoms[j].atom->getIsotope();
492 ivi = cipCode ==
"R" ? 2 : 1;
496 ivj = cipCode ==
"R" ? 2 : 1;
512 : dp_atoms(NULL), dp_mol(NULL), df_useNbrs(false){};
514 : dp_atoms(atoms), dp_mol(&m), df_useNbrs(false){};
519 int v = basecomp(i, j);
523 getAtomNeighborhood(dp_atoms[i].bonds);
524 getAtomNeighborhood(dp_atoms[j].bonds);
529 for (
unsigned int ii = 0;
530 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].
bonds.size();
533 dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii], ATNUM_CLASS_OFFSET);
536 for (
unsigned int ii = 0;
537 ii < dp_atoms[i].
bonds.size() && ii < dp_atoms[j].
bonds.size();
543 if (dp_atoms[i].bonds.size() < dp_atoms[j].
bonds.size()) {
545 }
else if (dp_atoms[i].bonds.size() > dp_atoms[j].
bonds.size()) {
558 template <
typename CompareFunc>
560 int mode,
int *order,
int *count,
int &activeset,
561 int *next,
int *changed,
char *touchedPartitions) {
573 while (activeset != -1) {
585 partition = activeset;
586 activeset = next[partition];
587 next[partition] = -2;
589 len = count[partition];
590 offset = atoms[partition].
index;
591 start = order + offset;
602 hanoisort(start, len, count, changed, compar);
609 for (
int k = 0; k < len; ++k) {
610 changed[start[k]] = 0;
616 for (i = count[index]; i < len; i++) {
618 if (count[index]) symclass = offset + i;
619 atoms[index].
index = symclass;
624 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
625 changed[atoms[index].
nbrIds[j]] = 1;
632 for (i = count[index]; i < len; i++) {
634 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
635 unsigned int nbor = atoms[index].
nbrIds[j];
636 touchedPartitions[atoms[nbor].
index] = 1;
639 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
640 if (touchedPartitions[ii]) {
641 partition = order[ii];
642 if ((count[partition] > 1) && (next[partition] == -2)) {
643 next[partition] = activeset;
644 activeset = partition;
646 touchedPartitions[ii] = 0;
653 template <
typename CompareFunc>
655 int mode,
int *order,
int *count,
int &activeset,
int *next,
656 int *changed,
char *touchedPartitions) {
664 for (
unsigned int i = 0; i < nAtoms; i++) {
665 partition = order[i];
666 oldPart = atoms[partition].
index;
667 while (count[partition] > 1) {
668 len = count[partition];
669 offset = atoms[partition].
index + len - 1;
670 index = order[offset];
671 atoms[index].
index = offset;
672 count[partition] = len - 1;
676 if (atoms[index].degree < 1) {
679 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
680 unsigned int nbor = atoms[index].
nbrIds[j];
681 touchedPartitions[atoms[nbor].
index] = 1;
685 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
686 if (touchedPartitions[ii]) {
687 int npart = order[ii];
688 if ((count[npart] > 1) && (next[npart] == -2)) {
689 next[npart] = activeset;
692 touchedPartitions[ii] = 0;
696 changed, touchedPartitions);
699 if (atoms[partition].index != oldPart) {
709 int &activeset,
int *next,
int *changed);
712 bool breakTies =
true,
bool includeChirality =
true,
713 bool includeIsotopes =
true);
716 const boost::dynamic_bitset<> &atomsInPlay,
717 const boost::dynamic_bitset<> &bondsInPlay,
718 const std::vector<std::string> *atomSymbols = NULL,
719 bool breakTies =
true,
bool includeChirality =
true,
720 bool includeIsotopes =
true);
725 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
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