RDKit
Open-source cheminformatics and machine learning.
new_canon.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2014 Greg Landrum
3 // Adapted from pseudo-code from Roger Sayle
4 //
5 // @@ All Rights Reserved @@
6 // This file is part of the RDKit.
7 // The contents are covered by the terms of the BSD license
8 // which is included in the file license.txt, found at the root
9 // of the RDKit source tree.
10 //
11 
12 #include <RDGeneral/export.h>
13 #include <RDGeneral/hanoiSort.h>
14 #include <GraphMol/ROMol.h>
15 #include <GraphMol/RingInfo.h>
17 #include <cstdint>
18 #include <boost/foreach.hpp>
19 #include <boost/dynamic_bitset.hpp>
21 #include <cstring>
22 #include <iostream>
23 #include <cassert>
24 #include <cstring>
25 #include <vector>
26 
27 //#define VERBOSE_CANON 1
28 
29 namespace RDKit {
30 namespace Canon {
31 
34  unsigned int bondStereo;
35  unsigned int nbrSymClass;
36  unsigned int nbrIdx;
38  : bondType(Bond::UNSPECIFIED),
39  bondStereo(static_cast<unsigned int>(Bond::STEREONONE)),
40  nbrSymClass(0),
41  nbrIdx(0){};
42  bondholder(Bond::BondType bt, Bond::BondStereo bs, unsigned int ni,
43  unsigned int nsc)
44  : bondType(bt),
45  bondStereo(static_cast<unsigned int>(bs)),
46  nbrSymClass(nsc),
47  nbrIdx(ni){};
48  bondholder(Bond::BondType bt, unsigned int bs, unsigned int ni,
49  unsigned int nsc)
50  : bondType(bt), bondStereo(bs), nbrSymClass(nsc), nbrIdx(ni){};
51  bool operator<(const bondholder &o) const {
52  if (bondType != o.bondType) return bondType < o.bondType;
53  if (bondStereo != o.bondStereo) return bondStereo < o.bondStereo;
54  return nbrSymClass < o.nbrSymClass;
55  }
56  static bool greater(const bondholder &lhs, const bondholder &rhs) {
57  if (lhs.bondType != rhs.bondType) return lhs.bondType > rhs.bondType;
58  if (lhs.bondStereo != rhs.bondStereo)
59  return lhs.bondStereo > rhs.bondStereo;
60  return lhs.nbrSymClass > rhs.nbrSymClass;
61  }
62 
63  static int compare(const bondholder &x, const bondholder &y,
64  unsigned int div = 1) {
65  if (x.bondType < y.bondType)
66  return -1;
67  else if (x.bondType > y.bondType)
68  return 1;
69  if (x.bondStereo < y.bondStereo)
70  return -1;
71  else if (x.bondStereo > y.bondStereo)
72  return 1;
73  return x.nbrSymClass / div - y.nbrSymClass / div;
74  }
75 };
76 
78  public:
79  const Atom *atom;
80  int index;
81  unsigned int degree;
82  unsigned int totalNumHs;
83  bool hasRingNbr;
85  int *nbrIds;
86  const std::string *p_symbol; // if provided, this is used to order atoms
87  std::vector<int> neighborNum;
88  std::vector<int> revistedNeighbors;
89  std::vector<bondholder> bonds;
90 
92  : atom(NULL),
93  index(-1),
94  degree(0),
95  totalNumHs(0),
96  hasRingNbr(false),
97  isRingStereoAtom(false),
98  nbrIds(NULL),
99  p_symbol(NULL){};
100 
101  ~canon_atom() { free(nbrIds); }
102 };
103 
105  canon_atom *atoms, std::vector<bondholder> &nbrs);
106 
108  canon_atom *atoms, std::vector<bondholder> &nbrs, unsigned int atomIdx,
109  std::vector<std::pair<unsigned int, unsigned int>> &result);
110 
111 /*
112  * Different types of atom compare functions:
113  *
114  * - SpecialChiralityAtomCompareFunctor: Allows canonizing molecules exhibiting
115  *dependent chirality
116  * - SpecialSymmetryAtomCompareFunctor: Very specialized, allows canonizing
117  *highly symmetrical graphs/molecules
118  * - AtomCompareFunctor: Basic atom compare function which also allows to
119  *include neighbors within the ranking
120  */
121 
123  public:
125  const ROMol *dp_mol;
126  const boost::dynamic_bitset<> *dp_atomsInPlay, *dp_bondsInPlay;
127 
129  : dp_atoms(NULL),
130  dp_mol(NULL),
131  dp_atomsInPlay(NULL),
132  dp_bondsInPlay(NULL){};
134  Canon::canon_atom *atoms, const ROMol &m,
135  const boost::dynamic_bitset<> *atomsInPlay = NULL,
136  const boost::dynamic_bitset<> *bondsInPlay = NULL)
137  : dp_atoms(atoms),
138  dp_mol(&m),
139  dp_atomsInPlay(atomsInPlay),
140  dp_bondsInPlay(bondsInPlay){};
141  int operator()(int i, int j) const {
142  PRECONDITION(dp_atoms, "no atoms");
143  PRECONDITION(dp_mol, "no molecule");
144  PRECONDITION(i != j, "bad call");
145  if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
146  return 0;
147  }
148 
149  if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
150  updateAtomNeighborIndex(dp_atoms, dp_atoms[i].bonds);
151  }
152  if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
153  updateAtomNeighborIndex(dp_atoms, dp_atoms[j].bonds);
154  }
155  for (unsigned int ii = 0;
156  ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
157  int cmp =
158  bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]);
159  if (cmp) return cmp;
160  }
161 
162  std::vector<std::pair<unsigned int, unsigned int>> swapsi;
163  std::vector<std::pair<unsigned int, unsigned int>> swapsj;
164  if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
165  updateAtomNeighborNumSwaps(dp_atoms, dp_atoms[i].bonds, i, swapsi);
166  }
167  if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
168  updateAtomNeighborNumSwaps(dp_atoms, dp_atoms[j].bonds, j, swapsj);
169  }
170  for (unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) {
171  int cmp = swapsi[ii].second - swapsj[ii].second;
172  if (cmp) return cmp;
173  }
174  return 0;
175  }
176 };
177 
179  public:
181  const ROMol *dp_mol;
182  const boost::dynamic_bitset<> *dp_atomsInPlay, *dp_bondsInPlay;
183 
185  : dp_atoms(NULL),
186  dp_mol(NULL),
187  dp_atomsInPlay(NULL),
188  dp_bondsInPlay(NULL){};
190  Canon::canon_atom *atoms, const ROMol &m,
191  const boost::dynamic_bitset<> *atomsInPlay = NULL,
192  const boost::dynamic_bitset<> *bondsInPlay = NULL)
193  : dp_atoms(atoms),
194  dp_mol(&m),
195  dp_atomsInPlay(atomsInPlay),
196  dp_bondsInPlay(bondsInPlay){};
197  int operator()(int i, int j) const {
198  PRECONDITION(dp_atoms, "no atoms");
199  PRECONDITION(dp_mol, "no molecule");
200  PRECONDITION(i != j, "bad call");
201  if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
202  return 0;
203  }
204 
205  if (dp_atoms[i].neighborNum < dp_atoms[j].neighborNum) {
206  return -1;
207  } else if (dp_atoms[i].neighborNum > dp_atoms[j].neighborNum) {
208  return 1;
209  }
210 
211  if (dp_atoms[i].revistedNeighbors < dp_atoms[j].revistedNeighbors) {
212  return -1;
213  } else if (dp_atoms[i].revistedNeighbors > dp_atoms[j].revistedNeighbors) {
214  return 1;
215  }
216 
217  if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
218  updateAtomNeighborIndex(dp_atoms, dp_atoms[i].bonds);
219  }
220  if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
221  updateAtomNeighborIndex(dp_atoms, dp_atoms[j].bonds);
222  }
223  for (unsigned int ii = 0;
224  ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size(); ++ii) {
225  int cmp =
226  bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]);
227  if (cmp) return cmp;
228  }
229 
230  if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
231  return -1;
232  } else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
233  return 1;
234  }
235  return 0;
236  }
237 };
238 
240  unsigned int getAtomRingNbrCode(unsigned int i) const {
241  if (!dp_atoms[i].hasRingNbr) return 0;
242 
243  int *nbrs = dp_atoms[i].nbrIds;
244  unsigned int code = 0;
245  for (unsigned j = 0; j < dp_atoms[i].degree; ++j) {
246  if (dp_atoms[nbrs[j]].isRingStereoAtom) {
247  code += dp_atoms[nbrs[j]].index * 10000 + 1; // j;
248  }
249  }
250  return code;
251  }
252 
253  int basecomp(int i, int j) const {
254  PRECONDITION(dp_atoms, "no atoms");
255  unsigned int ivi, ivj;
256 
257  // always start with the current class:
258  ivi = dp_atoms[i].index;
259  ivj = dp_atoms[j].index;
260  if (ivi < ivj)
261  return -1;
262  else if (ivi > ivj)
263  return 1;
264 
265  // use the atom-mapping numbers if they were assigned
266  /* boost::any_cast FILED here:
267  std::string molAtomMapNumber_i="";
268  std::string molAtomMapNumber_j="";
269  */
270  int molAtomMapNumber_i = 0;
271  int molAtomMapNumber_j = 0;
272  dp_atoms[i].atom->getPropIfPresent(common_properties::molAtomMapNumber,
273  molAtomMapNumber_i);
274  dp_atoms[j].atom->getPropIfPresent(common_properties::molAtomMapNumber,
275  molAtomMapNumber_j);
276  if (molAtomMapNumber_i < molAtomMapNumber_j)
277  return -1;
278  else if (molAtomMapNumber_i > molAtomMapNumber_j)
279  return 1;
280 
281  // start by comparing degree
282  ivi = dp_atoms[i].degree;
283  ivj = dp_atoms[j].degree;
284  if (ivi < ivj)
285  return -1;
286  else if (ivi > ivj)
287  return 1;
288 
289  if (dp_atoms[i].p_symbol && dp_atoms[j].p_symbol) {
290  if (*(dp_atoms[i].p_symbol) < *(dp_atoms[j].p_symbol))
291  return -1;
292  else if (*(dp_atoms[i].p_symbol) > *(dp_atoms[j].p_symbol))
293  return 1;
294  else
295  return 0;
296  }
297 
298  // move onto atomic number
299  ivi = dp_atoms[i].atom->getAtomicNum();
300  ivj = dp_atoms[j].atom->getAtomicNum();
301  if (ivi < ivj)
302  return -1;
303  else if (ivi > ivj)
304  return 1;
305 
306  // isotopes if we're using them
307  if (df_useIsotopes) {
308  ivi = dp_atoms[i].atom->getIsotope();
309  ivj = dp_atoms[j].atom->getIsotope();
310  if (ivi < ivj)
311  return -1;
312  else if (ivi > ivj)
313  return 1;
314  }
315 
316  // nHs
317  ivi = dp_atoms[i].totalNumHs;
318  ivj = dp_atoms[j].totalNumHs;
319  if (ivi < ivj)
320  return -1;
321  else if (ivi > ivj)
322  return 1;
323 
324  // charge
325  ivi = dp_atoms[i].atom->getFormalCharge();
326  ivj = dp_atoms[j].atom->getFormalCharge();
327  if (ivi < ivj)
328  return -1;
329  else if (ivi > ivj)
330  return 1;
331 
332  // chirality if we're using it
333  if (df_useChirality) {
334  // first atom stereochem:
335  ivi = 0;
336  ivj = 0;
337  std::string cipCode;
338  if (dp_atoms[i].atom->getPropIfPresent(common_properties::_CIPCode,
339  cipCode)) {
340  ivi = cipCode == "R" ? 2 : 1;
341  }
342  if (dp_atoms[j].atom->getPropIfPresent(common_properties::_CIPCode,
343  cipCode)) {
344  ivj = cipCode == "R" ? 2 : 1;
345  }
346  if (ivi < ivj)
347  return -1;
348  else if (ivi > ivj)
349  return 1;
350 
351  // can't actually use values here, because they are arbitrary
352  ivi = dp_atoms[i].atom->getChiralTag() != 0;
353  ivj = dp_atoms[j].atom->getChiralTag() != 0;
354  if (ivi < ivj)
355  return -1;
356  else if (ivi > ivj)
357  return 1;
358  }
359 
360  if (df_useChiralityRings) {
361  // ring stereochemistry
362  ivi = getAtomRingNbrCode(i);
363  ivj = getAtomRingNbrCode(j);
364  if (ivi < ivj)
365  return -1;
366  else if (ivi > ivj)
367  return 1;
368  // bond stereo is taken care of in the neighborhood comparison
369  }
370  return 0;
371  }
372 
373  public:
375  const ROMol *dp_mol;
376  const boost::dynamic_bitset<> *dp_atomsInPlay, *dp_bondsInPlay;
381 
383  : dp_atoms(NULL),
384  dp_mol(NULL),
385  dp_atomsInPlay(NULL),
386  dp_bondsInPlay(NULL),
387  df_useNbrs(false),
388  df_useIsotopes(true),
389  df_useChirality(true),
390  df_useChiralityRings(true){};
392  const boost::dynamic_bitset<> *atomsInPlay = NULL,
393  const boost::dynamic_bitset<> *bondsInPlay = NULL)
394  : dp_atoms(atoms),
395  dp_mol(&m),
396  dp_atomsInPlay(atomsInPlay),
397  dp_bondsInPlay(bondsInPlay),
398  df_useNbrs(false),
399  df_useIsotopes(true),
400  df_useChirality(true),
401  df_useChiralityRings(true){};
402  int operator()(int i, int j) const {
403  PRECONDITION(dp_atoms, "no atoms");
404  PRECONDITION(dp_mol, "no molecule");
405  PRECONDITION(i != j, "bad call");
406  if (dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])) {
407  return 0;
408  }
409 
410  int v = basecomp(i, j);
411  if (v) {
412  return v;
413  }
414 
415  if (df_useNbrs) {
416  if (!dp_atomsInPlay || (*dp_atomsInPlay)[i]) {
417  updateAtomNeighborIndex(dp_atoms, dp_atoms[i].bonds);
418  }
419  if (!dp_atomsInPlay || (*dp_atomsInPlay)[j]) {
420  updateAtomNeighborIndex(dp_atoms, dp_atoms[j].bonds);
421  }
422 
423  for (unsigned int ii = 0;
424  ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
425  ++ii) {
426  int cmp =
427  bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]);
428  if (cmp) return cmp;
429  }
430 
431  if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
432  return -1;
433  } else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
434  return 1;
435  }
436  }
437  return 0;
438  }
439 };
440 
441 /*
442  * A compare function to discriminate chiral atoms, similar to the CIP rules.
443  * This functionality is currently not used.
444  */
445 
446 const unsigned int ATNUM_CLASS_OFFSET = 10000;
448  void getAtomNeighborhood(std::vector<bondholder> &nbrs) const {
449  for (unsigned j = 0; j < nbrs.size(); ++j) {
450  unsigned int nbrIdx = nbrs[j].nbrIdx;
451  if (nbrIdx == ATNUM_CLASS_OFFSET) {
452  // Ignore the Hs
453  continue;
454  }
455  const Atom *nbr = dp_atoms[nbrIdx].atom;
456  nbrs[j].nbrSymClass =
457  nbr->getAtomicNum() * ATNUM_CLASS_OFFSET + dp_atoms[nbrIdx].index + 1;
458  }
459  std::sort(nbrs.begin(), nbrs.end(), bondholder::greater);
460  // FIX: don't want to be doing this long-term
461  }
462 
463  int basecomp(int i, int j) const {
464  PRECONDITION(dp_atoms, "no atoms");
465  unsigned int ivi, ivj;
466 
467  // always start with the current class:
468  ivi = dp_atoms[i].index;
469  ivj = dp_atoms[j].index;
470  if (ivi < ivj)
471  return -1;
472  else if (ivi > ivj)
473  return 1;
474 
475  // move onto atomic number
476  ivi = dp_atoms[i].atom->getAtomicNum();
477  ivj = dp_atoms[j].atom->getAtomicNum();
478  if (ivi < ivj)
479  return -1;
480  else if (ivi > ivj)
481  return 1;
482 
483  // isotopes:
484  ivi = dp_atoms[i].atom->getIsotope();
485  ivj = dp_atoms[j].atom->getIsotope();
486  if (ivi < ivj)
487  return -1;
488  else if (ivi > ivj)
489  return 1;
490 
491  // atom stereochem:
492  ivi = 0;
493  ivj = 0;
494  std::string cipCode;
495  if (dp_atoms[i].atom->getPropIfPresent(common_properties::_CIPCode,
496  cipCode)) {
497  ivi = cipCode == "R" ? 2 : 1;
498  }
499  if (dp_atoms[j].atom->getPropIfPresent(common_properties::_CIPCode,
500  cipCode)) {
501  ivj = cipCode == "R" ? 2 : 1;
502  }
503  if (ivi < ivj)
504  return -1;
505  else if (ivi > ivj)
506  return 1;
507 
508  // bond stereo is taken care of in the neighborhood comparison
509  return 0;
510  }
511 
512  public:
514  const ROMol *dp_mol;
517  : dp_atoms(NULL), dp_mol(NULL), df_useNbrs(false){};
519  : dp_atoms(atoms), dp_mol(&m), df_useNbrs(false){};
520  int operator()(int i, int j) const {
521  PRECONDITION(dp_atoms, "no atoms");
522  PRECONDITION(dp_mol, "no molecule");
523  PRECONDITION(i != j, "bad call");
524  int v = basecomp(i, j);
525  if (v) return v;
526 
527  if (df_useNbrs) {
528  getAtomNeighborhood(dp_atoms[i].bonds);
529  getAtomNeighborhood(dp_atoms[j].bonds);
530 
531  // we do two passes through the neighbor lists. The first just uses the
532  // atomic numbers (by passing the optional 10000 to bondholder::compare),
533  // the second takes the already-computed index into account
534  for (unsigned int ii = 0;
535  ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
536  ++ii) {
537  int cmp = bondholder::compare(
538  dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii], ATNUM_CLASS_OFFSET);
539  if (cmp) return cmp;
540  }
541  for (unsigned int ii = 0;
542  ii < dp_atoms[i].bonds.size() && ii < dp_atoms[j].bonds.size();
543  ++ii) {
544  int cmp =
545  bondholder::compare(dp_atoms[i].bonds[ii], dp_atoms[j].bonds[ii]);
546  if (cmp) return cmp;
547  }
548  if (dp_atoms[i].bonds.size() < dp_atoms[j].bonds.size()) {
549  return -1;
550  } else if (dp_atoms[i].bonds.size() > dp_atoms[j].bonds.size()) {
551  return 1;
552  }
553  }
554  return 0;
555  }
556 };
557 
558 /*
559  * Basic canonicalization function to organize the partitions which will be
560  * sorted next.
561  * */
562 
563 template <typename CompareFunc>
564 void RefinePartitions(const ROMol &mol, canon_atom *atoms, CompareFunc compar,
565  int mode, int *order, int *count, int &activeset,
566  int *next, int *changed, char *touchedPartitions) {
567  unsigned int nAtoms = mol.getNumAtoms();
568  int partition;
569  int symclass = 0;
570  int *start;
571  int offset;
572  int index;
573  int len;
574  int i;
575  // std::vector<char> touchedPartitions(mol.getNumAtoms(),0);
576 
577  // std::cerr<<"&&&&&&&&&&&&&&&& RP"<<std::endl;
578  while (activeset != -1) {
579  // std::cerr<<"ITER: "<<activeset<<" next: "<<next[activeset]<<std::endl;
580  // std::cerr<<" next: ";
581  // for(unsigned int ii=0;ii<nAtoms;++ii){
582  // std::cerr<<ii<<":"<<next[ii]<<" ";
583  // }
584  // std::cerr<<std::endl;
585  // for(unsigned int ii=0;ii<nAtoms;++ii){
586  // std::cerr<<order[ii]<<" count: "<<count[order[ii]]<<" index:
587  // "<<atoms[order[ii]].index<<std::endl;
588  // }
589 
590  partition = activeset;
591  activeset = next[partition];
592  next[partition] = -2;
593 
594  len = count[partition];
595  offset = atoms[partition].index;
596  start = order + offset;
597  // std::cerr<<"\n\n**************************************************************"<<std::endl;
598  // std::cerr<<" sort - class:"<<atoms[partition].index<<" len: "<<len<<":";
599  // for(unsigned int ii=0;ii<len;++ii){
600  // std::cerr<<" "<<order[offset+ii]+1;
601  // }
602  // std::cerr<<std::endl;
603  // for(unsigned int ii=0;ii<nAtoms;++ii){
604  // std::cerr<<order[ii]+1<<" count: "<<count[order[ii]]<<" index:
605  // "<<atoms[order[ii]].index<<std::endl;
606  // }
607  hanoisort(start, len, count, changed, compar);
608  // std::cerr<<"*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*"<<std::endl;
609  // std::cerr<<" result:";
610  // for(unsigned int ii=0;ii<nAtoms;++ii){
611  // std::cerr<<order[ii]+1<<" count: "<<count[order[ii]]<<" index:
612  // "<<atoms[order[ii]].index<<std::endl;
613  // }
614  for (int k = 0; k < len; ++k) {
615  changed[start[k]] = 0;
616  }
617 
618  index = start[0];
619  // std::cerr<<" len:"<<len<<" index:"<<index<<"
620  // count:"<<count[index]<<std::endl;
621  for (i = count[index]; i < len; i++) {
622  index = start[i];
623  if (count[index]) symclass = offset + i;
624  atoms[index].index = symclass;
625  // std::cerr<<" "<<index+1<<"("<<symclass<<")";
626  // if(mode && (activeset<0 || count[index]>count[activeset]) ){
627  // activeset=index;
628  //}
629  for (unsigned j = 0; j < atoms[index].degree; ++j) {
630  changed[atoms[index].nbrIds[j]] = 1;
631  }
632  }
633  // std::cerr<<std::endl;
634 
635  if (mode) {
636  index = start[0];
637  for (i = count[index]; i < len; i++) {
638  index = start[i];
639  for (unsigned j = 0; j < atoms[index].degree; ++j) {
640  unsigned int nbor = atoms[index].nbrIds[j];
641  touchedPartitions[atoms[nbor].index] = 1;
642  }
643  }
644  for (unsigned int ii = 0; ii < nAtoms; ++ii) {
645  if (touchedPartitions[ii]) {
646  partition = order[ii];
647  if ((count[partition] > 1) && (next[partition] == -2)) {
648  next[partition] = activeset;
649  activeset = partition;
650  }
651  touchedPartitions[ii] = 0;
652  }
653  }
654  }
655  }
656 } // end of RefinePartitions()
657 
658 template <typename CompareFunc>
659 void BreakTies(const ROMol &mol, canon_atom *atoms, CompareFunc compar,
660  int mode, int *order, int *count, int &activeset, int *next,
661  int *changed, char *touchedPartitions) {
662  unsigned int nAtoms = mol.getNumAtoms();
663  int partition;
664  int offset;
665  int index;
666  int len;
667  int oldPart = 0;
668 
669  for (unsigned int i = 0; i < nAtoms; i++) {
670  partition = order[i];
671  oldPart = atoms[partition].index;
672  while (count[partition] > 1) {
673  len = count[partition];
674  offset = atoms[partition].index + len - 1;
675  index = order[offset];
676  atoms[index].index = offset;
677  count[partition] = len - 1;
678  count[index] = 1;
679 
680  // test for ions, water molecules with no
681  if (atoms[index].degree < 1) {
682  continue;
683  }
684  for (unsigned j = 0; j < atoms[index].degree; ++j) {
685  unsigned int nbor = atoms[index].nbrIds[j];
686  touchedPartitions[atoms[nbor].index] = 1;
687  changed[nbor] = 1;
688  }
689 
690  for (unsigned int ii = 0; ii < nAtoms; ++ii) {
691  if (touchedPartitions[ii]) {
692  int npart = order[ii];
693  if ((count[npart] > 1) && (next[npart] == -2)) {
694  next[npart] = activeset;
695  activeset = npart;
696  }
697  touchedPartitions[ii] = 0;
698  }
699  }
700  RefinePartitions(mol, atoms, compar, mode, order, count, activeset, next,
701  changed, touchedPartitions);
702  }
703  // not sure if this works each time
704  if (atoms[partition].index != oldPart) {
705  i -= 1;
706  }
707  }
708 } // end of BreakTies()
709 
710 RDKIT_GRAPHMOL_EXPORT void CreateSinglePartition(unsigned int nAtoms,
711  int *order, int *count,
712  canon_atom *atoms);
713 
714 RDKIT_GRAPHMOL_EXPORT void ActivatePartitions(unsigned int nAtoms, int *order,
715  int *count, int &activeset,
716  int *next, int *changed);
717 
719  std::vector<unsigned int> &res,
720  bool breakTies = true,
721  bool includeChirality = true,
722  bool includeIsotopes = true);
723 
725  const ROMol &mol, std::vector<unsigned int> &res,
726  const boost::dynamic_bitset<> &atomsInPlay,
727  const boost::dynamic_bitset<> &bondsInPlay,
728  const std::vector<std::string> *atomSymbols = NULL, bool breakTies = true,
729  bool includeChirality = true, bool includeIsotopes = true);
730 
732  std::vector<unsigned int> &res);
733 
735  std::vector<Canon::canon_atom> &atoms,
736  bool includeChirality = true);
737 
738 } // namespace Canon
739 } // namespace RDKit
RDKit::Canon::ChiralAtomCompareFunctor::df_useNbrs
bool df_useNbrs
Definition: new_canon.h:515
RDKit::Canon::bondholder::bondholder
bondholder(Bond::BondType bt, unsigned int bs, unsigned int ni, unsigned int nsc)
Definition: new_canon.h:48
RDKit::Canon::SpecialSymmetryAtomCompareFunctor::SpecialSymmetryAtomCompareFunctor
SpecialSymmetryAtomCompareFunctor()
Definition: new_canon.h:184
RDKit::Canon::canon_atom::totalNumHs
unsigned int totalNumHs
Definition: new_canon.h:82
RDKit::Canon::canon_atom::neighborNum
std::vector< int > neighborNum
Definition: new_canon.h:87
RDKit::Canon::bondholder::nbrIdx
unsigned int nbrIdx
Definition: new_canon.h:36
ROMol.h
Defines the primary molecule class ROMol as well as associated typedefs.
RDKit::Canon::SpecialChiralityAtomCompareFunctor::dp_bondsInPlay
const boost::dynamic_bitset * dp_bondsInPlay
Definition: new_canon.h:126
RDKit::Canon::SpecialSymmetryAtomCompareFunctor::SpecialSymmetryAtomCompareFunctor
SpecialSymmetryAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=NULL, const boost::dynamic_bitset<> *bondsInPlay=NULL)
Definition: new_canon.h:189
BoostStartInclude.h
RDKit::Canon::canon_atom::degree
unsigned int degree
Definition: new_canon.h:81
RDKit::Canon::AtomCompareFunctor::AtomCompareFunctor
AtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=NULL, const boost::dynamic_bitset<> *bondsInPlay=NULL)
Definition: new_canon.h:391
RDKit::Bond
class for representing a bond
Definition: Bond.h:47
RDKit::Canon::bondholder::bondType
Bond::BondType bondType
Definition: new_canon.h:33
RDKit::Canon::updateAtomNeighborNumSwaps
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::Canon::AtomCompareFunctor::df_useChirality
bool df_useChirality
Definition: new_canon.h:379
RDKit::Canon::bondholder::operator<
bool operator<(const bondholder &o) const
Definition: new_canon.h:51
RDKit::Canon::rankFragmentAtoms
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=NULL, bool breakTies=true, bool includeChirality=true, bool includeIsotopes=true)
RDKit::Canon::SpecialSymmetryAtomCompareFunctor::dp_mol
const ROMol * dp_mol
Definition: new_canon.h:181
RDKit::Canon::AtomCompareFunctor::df_useIsotopes
bool df_useIsotopes
Definition: new_canon.h:378
RDKit::Canon::canon_atom::hasRingNbr
bool hasRingNbr
Definition: new_canon.h:83
RDKit::Canon::SpecialSymmetryAtomCompareFunctor::operator()
int operator()(int i, int j) const
Definition: new_canon.h:197
RDKit::Atom::getAtomicNum
int getAtomicNum() const
returns our atomic number
Definition: Atom.h:116
RDKit::Bond::BondType
BondType
the type of Bond
Definition: Bond.h:56
RDKit::Canon::RefinePartitions
void RefinePartitions(const ROMol &mol, canon_atom *atoms, CompareFunc compar, int mode, int *order, int *count, int &activeset, int *next, int *changed, char *touchedPartitions)
Definition: new_canon.h:564
RDKit::Canon::bondholder::bondholder
bondholder(Bond::BondType bt, Bond::BondStereo bs, unsigned int ni, unsigned int nsc)
Definition: new_canon.h:42
RDKit::Canon::SpecialChiralityAtomCompareFunctor::operator()
int operator()(int i, int j) const
Definition: new_canon.h:141
RDKit::Canon::ChiralAtomCompareFunctor
Definition: new_canon.h:447
RDKit::Canon::ActivatePartitions
RDKIT_GRAPHMOL_EXPORT void ActivatePartitions(unsigned int nAtoms, int *order, int *count, int &activeset, int *next, int *changed)
RDKit::Atom
The class for representing atoms.
Definition: Atom.h:69
BoostEndInclude.h
RDKit::Canon::rankMolAtoms
RDKIT_GRAPHMOL_EXPORT void rankMolAtoms(const ROMol &mol, std::vector< unsigned int > &res, bool breakTies=true, bool includeChirality=true, bool includeIsotopes=true)
RDKit::Canon::ChiralAtomCompareFunctor::dp_atoms
Canon::canon_atom * dp_atoms
Definition: new_canon.h:513
RDKit::Canon::SpecialSymmetryAtomCompareFunctor::dp_bondsInPlay
const boost::dynamic_bitset * dp_bondsInPlay
Definition: new_canon.h:182
RDKit::Canon::AtomCompareFunctor::dp_atoms
Canon::canon_atom * dp_atoms
Definition: new_canon.h:374
RDKit::Canon::AtomCompareFunctor::dp_bondsInPlay
const boost::dynamic_bitset * dp_bondsInPlay
Definition: new_canon.h:376
RDKit::Canon::AtomCompareFunctor::AtomCompareFunctor
AtomCompareFunctor()
Definition: new_canon.h:382
RDKit::ROMol
Definition: ROMol.h:171
RDKit::Canon::updateAtomNeighborIndex
RDKIT_GRAPHMOL_EXPORT void updateAtomNeighborIndex(canon_atom *atoms, std::vector< bondholder > &nbrs)
RDKit::Canon::AtomCompareFunctor::df_useChiralityRings
bool df_useChiralityRings
Definition: new_canon.h:380
RDKit::Canon::AtomCompareFunctor::operator()
int operator()(int i, int j) const
Definition: new_canon.h:402
RDKit::Canon::bondholder::bondholder
bondholder()
Definition: new_canon.h:37
RDKIT_GRAPHMOL_EXPORT
#define RDKIT_GRAPHMOL_EXPORT
Definition: export.h:307
RDKit::Canon::CreateSinglePartition
RDKIT_GRAPHMOL_EXPORT void CreateSinglePartition(unsigned int nAtoms, int *order, int *count, canon_atom *atoms)
RDKit::Canon::ATNUM_CLASS_OFFSET
const unsigned int ATNUM_CLASS_OFFSET
Definition: new_canon.h:446
RDKit::Canon::bondholder
Definition: new_canon.h:32
RDKit::Canon::AtomCompareFunctor
Definition: new_canon.h:239
RDKit::Canon::ChiralAtomCompareFunctor::ChiralAtomCompareFunctor
ChiralAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m)
Definition: new_canon.h:518
RDKit::common_properties::_CIPCode
const RDKIT_RDGENERAL_EXPORT std::string _CIPCode
RDKit::Canon::SpecialChiralityAtomCompareFunctor
Definition: new_canon.h:122
RDKit::Canon::canon_atom::bonds
std::vector< bondholder > bonds
Definition: new_canon.h:89
RDKit::Canon::bondholder::compare
static int compare(const bondholder &x, const bondholder &y, unsigned int div=1)
Definition: new_canon.h:63
RDKit::Canon::bondholder::greater
static bool greater(const bondholder &lhs, const bondholder &rhs)
Definition: new_canon.h:56
RDKit::Canon::canon_atom::revistedNeighbors
std::vector< int > revistedNeighbors
Definition: new_canon.h:88
RDKit::Canon::SpecialChiralityAtomCompareFunctor::SpecialChiralityAtomCompareFunctor
SpecialChiralityAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=NULL, const boost::dynamic_bitset<> *bondsInPlay=NULL)
Definition: new_canon.h:133
RDKit::Canon::SpecialChiralityAtomCompareFunctor::dp_atoms
Canon::canon_atom * dp_atoms
Definition: new_canon.h:124
RDKit::Canon::bondholder::nbrSymClass
unsigned int nbrSymClass
Definition: new_canon.h:35
RDKit::ROMol::getNumAtoms
unsigned int getNumAtoms(bool onlyExplicit=1) const
returns our number of atoms
RDKit::Canon::canon_atom::~canon_atom
~canon_atom()
Definition: new_canon.h:101
RDKit
Std stuff.
Definition: Atom.h:30
RDKit::Canon::ChiralAtomCompareFunctor::operator()
int operator()(int i, int j) const
Definition: new_canon.h:520
RDKit::Canon::canon_atom::index
int index
Definition: new_canon.h:80
RDKit::Canon::SpecialSymmetryAtomCompareFunctor::dp_atoms
Canon::canon_atom * dp_atoms
Definition: new_canon.h:180
RDKit::Canon::SpecialChiralityAtomCompareFunctor::SpecialChiralityAtomCompareFunctor
SpecialChiralityAtomCompareFunctor()
Definition: new_canon.h:128
RDKit::Canon::canon_atom
Definition: new_canon.h:77
hanoiSort.h
RDKit::Canon::ChiralAtomCompareFunctor::ChiralAtomCompareFunctor
ChiralAtomCompareFunctor()
Definition: new_canon.h:516
RDKit::Canon::canon_atom::nbrIds
int * nbrIds
Definition: new_canon.h:85
PRECONDITION
#define PRECONDITION(expr, mess)
Definition: Invariant.h:109
RDKit::Canon::canon_atom::p_symbol
const std::string * p_symbol
Definition: new_canon.h:86
RDKit::hanoisort
void hanoisort(int *base, int nel, int *count, int *changed, CompareFunc compar)
Definition: hanoiSort.h:145
RDKit::Canon::AtomCompareFunctor::dp_mol
const ROMol * dp_mol
Definition: new_canon.h:375
RDKit::Canon::ChiralAtomCompareFunctor::dp_mol
const ROMol * dp_mol
Definition: new_canon.h:514
RDKit::Canon::chiralRankMolAtoms
RDKIT_GRAPHMOL_EXPORT void chiralRankMolAtoms(const ROMol &mol, std::vector< unsigned int > &res)
RDKit::Canon::SpecialSymmetryAtomCompareFunctor
Definition: new_canon.h:178
RDKit::Canon::SpecialChiralityAtomCompareFunctor::dp_mol
const ROMol * dp_mol
Definition: new_canon.h:125
RDKit::Canon::canon_atom::atom
const Atom * atom
Definition: new_canon.h:79
RDKit::Canon::canon_atom::canon_atom
canon_atom()
Definition: new_canon.h:91
RDKit::Canon::bondholder::bondStereo
unsigned int bondStereo
Definition: new_canon.h:34
RDKit::Bond::BondStereo
BondStereo
the nature of the bond's stereochem (for cis/trans)
Definition: Bond.h:95
RDKit::Canon::canon_atom::isRingStereoAtom
bool isRingStereoAtom
Definition: new_canon.h:84
RDKit::common_properties::molAtomMapNumber
const RDKIT_RDGENERAL_EXPORT std::string molAtomMapNumber
RDKit::Canon::initCanonAtoms
RDKIT_GRAPHMOL_EXPORT void initCanonAtoms(const ROMol &mol, std::vector< Canon::canon_atom > &atoms, bool includeChirality=true)
RingInfo.h
RDKit::Canon::AtomCompareFunctor::df_useNbrs
bool df_useNbrs
Definition: new_canon.h:377
RDKit::Canon::BreakTies
void BreakTies(const ROMol &mol, canon_atom *atoms, CompareFunc compar, int mode, int *order, int *count, int &activeset, int *next, int *changed, char *touchedPartitions)
Definition: new_canon.h:659
export.h