19#include <boost/dynamic_bitset.hpp>
46 unsigned int nsc,
unsigned int bidx)
53 unsigned int nsc,
unsigned int bidx)
68 unsigned int div = 1) {
117 canon_atom *atoms, std::vector<bondholder> &nbrs);
120 canon_atom *atoms, std::vector<bondholder> &nbrs,
unsigned int atomIdx,
121 std::vector<std::pair<unsigned int, unsigned int>> &result);
144 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
145 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
164 for (
unsigned int ii = 0;
173 std::vector<std::pair<unsigned int, unsigned int>> swapsi;
174 std::vector<std::pair<unsigned int, unsigned int>> swapsj;
182 for (
unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) {
183 int cmp = swapsi[ii].second - swapsj[ii].second;
204 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
205 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
236 for (
unsigned int ii = 0;
255unsigned int getChiralRank(
const ROMol *dp_mol, canon_atom *dp_atoms,
257 unsigned int res = 0;
258 std::vector<unsigned int> perm;
259 perm.reserve(dp_atoms[i].atom->getDegree());
260 for (
const auto nbr : dp_mol->
atomNeighbors(dp_atoms[i].atom)) {
261 auto rnk = dp_atoms[nbr->getIdx()].index;
263 if (std::find(perm.begin(), perm.end(), rnk) != perm.end()) {
269 if (perm.size() == dp_atoms[i].atom->getDegree()) {
270 auto ctag = dp_atoms[i].atom->getChiralTag();
273 auto sortedPerm = perm;
274 std::sort(sortedPerm.begin(), sortedPerm.end());
278 res = res == 2 ? 1 : 2;
286 unsigned int getAtomRingNbrCode(
unsigned int i)
const {
291 auto nbrs =
dp_atoms[i].nbrIds.get();
292 unsigned int code = 0;
293 for (
unsigned j = 0; j <
dp_atoms[i].degree; ++j) {
294 if (
dp_atoms[nbrs[j]].isRingStereoAtom) {
295 code +=
dp_atoms[nbrs[j]].index * 10000 + 1;
301 int basecomp(
int i,
int j)
const {
302 unsigned int ivi, ivj;
309 }
else if (ivi > ivj) {
315 int rankingNumber_i = 0;
316 int rankingNumber_j = 0;
321 if (rankingNumber_i < rankingNumber_j) {
323 }
else if (rankingNumber_i > rankingNumber_j) {
330 int molAtomMapNumber_i = 0;
331 int molAtomMapNumber_j = 0;
342 if (molAtomMapNumber_i < molAtomMapNumber_j) {
344 }
else if (molAtomMapNumber_i > molAtomMapNumber_j) {
353 }
else if (ivi > ivj) {
367 ivi =
dp_atoms[i].atom->getAtomicNum();
368 ivj =
dp_atoms[j].atom->getAtomicNum();
371 }
else if (ivi > ivj) {
376 ivi =
dp_atoms[i].atom->getIsotope();
377 ivj =
dp_atoms[j].atom->getIsotope();
380 }
else if (ivi > ivj) {
390 }
else if (ivi > ivj) {
394 ivi =
dp_atoms[i].atom->getFormalCharge();
395 ivj =
dp_atoms[j].atom->getFormalCharge();
398 }
else if (ivi > ivj) {
409 }
else if (ivi > ivj) {
422 }
else if (ivj && !ivi) {
424 }
else if (ivi && ivj) {
425 auto iType =
dp_atoms[i].typeOfStereoGroup;
426 auto jType =
dp_atoms[j].typeOfStereoGroup;
429 }
else if (iType > jType) {
434 std::set<unsigned int> sgi;
435 for (
const auto sgat :
436 dp_mol->getStereoGroups()[ivi - 1].getAtoms()) {
437 sgi.insert(
dp_atoms[sgat->getIdx()].index);
439 std::set<unsigned int> sgj;
440 for (
const auto sgat :
441 dp_mol->getStereoGroups()[ivj - 1].getAtoms()) {
442 sgj.insert(
dp_atoms[sgat->getIdx()].index);
446 }
else if (sgi > sgj) {
455 }
else if (ivi > ivj) {
467 ivi =
dp_atoms[i].atom->getChiralTag() != 0;
468 ivj =
dp_atoms[j].atom->getChiralTag() != 0;
471 }
else if (ivi > ivj) {
484 }
else if (ivi > ivj) {
493 ivi = getAtomRingNbrCode(i);
494 ivj = getAtomRingNbrCode(j);
497 }
else if (ivi > ivj) {
520 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
521 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
531 int v = basecomp(i, j);
544 for (
unsigned int ii = 0;
571 void getAtomNeighborhood(std::vector<bondholder> &nbrs)
const {
572 for (
unsigned j = 0; j < nbrs.size(); ++j) {
573 unsigned int nbrIdx = nbrs[j].nbrIdx;
579 nbrs[j].nbrSymClass =
586 int basecomp(
int i,
int j)
const {
588 unsigned int ivi, ivj;
595 }
else if (ivi > ivj) {
600 ivi =
dp_atoms[i].atom->getAtomicNum();
601 ivj =
dp_atoms[j].atom->getAtomicNum();
604 }
else if (ivi > ivj) {
609 ivi =
dp_atoms[i].atom->getIsotope();
610 ivj =
dp_atoms[j].atom->getIsotope();
613 }
else if (ivi > ivj) {
623 ivi = cipCode ==
"R" ? 2 : 1;
627 ivj = cipCode ==
"R" ? 2 : 1;
631 }
else if (ivi > ivj) {
650 int v = basecomp(i, j);
656 getAtomNeighborhood(
dp_atoms[i].bonds);
657 getAtomNeighborhood(
dp_atoms[j].bonds);
662 for (
unsigned int ii = 0;
671 for (
unsigned int ii = 0;
695template <
typename CompareFunc>
697 int mode,
int *order,
int *count,
int &activeset,
698 int *next,
int *changed,
char *touchedPartitions) {
710 while (activeset != -1) {
722 partition = activeset;
723 activeset = next[partition];
724 next[partition] = -2;
726 len = count[partition];
727 offset = atoms[partition].
index;
728 start = order + offset;
739 hanoisort(start, len, count, changed, compar);
746 for (
int k = 0; k < len; ++k) {
747 changed[start[k]] = 0;
753 for (i = count[index]; i < len; i++) {
756 symclass = offset + i;
758 atoms[index].
index = symclass;
763 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
764 changed[atoms[index].
nbrIds[j]] = 1;
771 for (i = count[index]; i < len; i++) {
773 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
774 unsigned int nbor = atoms[index].
nbrIds[j];
775 touchedPartitions[atoms[nbor].
index] = 1;
778 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
779 if (touchedPartitions[ii]) {
780 partition = order[ii];
781 if ((count[partition] > 1) && (next[partition] == -2)) {
782 next[partition] = activeset;
783 activeset = partition;
785 touchedPartitions[ii] = 0;
792template <
typename CompareFunc>
794 int mode,
int *order,
int *count,
int &activeset,
int *next,
795 int *changed,
char *touchedPartitions) {
803 for (
unsigned int i = 0; i < nAtoms; i++) {
804 partition = order[i];
805 oldPart = atoms[partition].
index;
806 while (count[partition] > 1) {
807 len = count[partition];
808 offset = atoms[partition].
index + len - 1;
809 index = order[offset];
810 atoms[index].
index = offset;
811 count[partition] = len - 1;
815 if (atoms[index].degree < 1) {
818 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
819 unsigned int nbor = atoms[index].
nbrIds[j];
820 touchedPartitions[atoms[nbor].
index] = 1;
824 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
825 if (touchedPartitions[ii]) {
826 int npart = order[ii];
827 if ((count[npart] > 1) && (next[npart] == -2)) {
828 next[npart] = activeset;
831 touchedPartitions[ii] = 0;
835 changed, touchedPartitions);
838 if (atoms[partition].index != oldPart) {
845 int *order,
int *count,
849 int *count,
int &activeset,
850 int *next,
int *changed);
854 const ROMol &mol, std::vector<unsigned int> &res,
bool breakTies =
true,
855 bool includeChirality =
true,
bool includeIsotopes =
true,
856 bool includeAtomMaps =
true,
bool includeChiralPresence =
false,
857 bool includeStereoGroups =
true,
bool useNonStereoRanks =
false,
858 bool includeRingStereo =
true);
862 const ROMol &mol, std::vector<unsigned int> &res,
863 const boost::dynamic_bitset<> &atomsInPlay,
864 const boost::dynamic_bitset<> &bondsInPlay,
865 const std::vector<std::string> *atomSymbols,
866 const std::vector<std::string> *bondSymbols,
bool breakTies,
867 bool includeChirality,
bool includeIsotope,
bool includeAtomMaps,
868 bool includeChiralPresence,
bool includeRingStereo =
true);
872 const ROMol &mol, std::vector<unsigned int> &res,
873 const boost::dynamic_bitset<> &atomsInPlay,
874 const boost::dynamic_bitset<> &bondsInPlay,
875 const std::vector<std::string> *atomSymbols =
nullptr,
876 bool breakTies =
true,
bool includeChirality =
true,
877 bool includeIsotopes =
true,
bool includeAtomMaps =
true,
878 bool includeChiralPresence =
false,
bool includeRingStereo =
true) {
880 breakTies, includeChirality, includeIsotopes,
881 includeAtomMaps, includeChiralPresence, includeRingStereo);
885 std::vector<unsigned int> &res);
888 std::vector<Canon::canon_atom> &atoms,
889 bool includeChirality =
true,
890 bool includeStereoGroups =
true);
894 std::vector<Canon::canon_atom> &atoms,
895 bool includeChirality,
896 const std::vector<std::string> *atomSymbols,
897 const std::vector<std::string> *bondSymbols,
898 const boost::dynamic_bitset<> &atomsInPlay,
899 const boost::dynamic_bitset<> &bondsInPlay,
903 bool useSpecial =
false,
bool useChirality =
false,
904 bool includeRingStereo =
true,
905 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
906 const boost::dynamic_bitset<> *bondsInPlay =
nullptr);
#define PRECONDITION(expr, mess)
Defines the primary molecule class ROMol as well as associated typedefs.
Defines the class StereoGroup which stores relationships between the absolute configurations of atoms...
The class for representing atoms.
int getAtomicNum() const
returns our atomic number
@ CHI_TETRAHEDRAL_CW
tetrahedral: clockwise rotation (SMILES @@)
@ CHI_UNSPECIFIED
chirality that hasn't been specified
@ CHI_TETRAHEDRAL_CCW
tetrahedral: counter-clockwise rotation (SMILES
BondStereo
the nature of the bond's stereochem (for cis/trans)
const boost::dynamic_bitset * dp_bondsInPlay
AtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=nullptr, const boost::dynamic_bitset<> *bondsInPlay=nullptr)
bool df_useAtomMapsOnDummies
int operator()(int i, int j) const
const boost::dynamic_bitset * dp_atomsInPlay
bool df_useNonStereoRanks
bool df_useChiralityRings
bool df_useChiralPresence
Canon::canon_atom * dp_atoms
ChiralAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m)
int operator()(int i, int j) const
ChiralAtomCompareFunctor()
Canon::canon_atom * dp_atoms
const boost::dynamic_bitset * dp_atomsInPlay
int operator()(int i, int j) const
const boost::dynamic_bitset * dp_bondsInPlay
Canon::canon_atom * dp_atoms
SpecialChiralityAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=nullptr, const boost::dynamic_bitset<> *bondsInPlay=nullptr)
SpecialChiralityAtomCompareFunctor()
Canon::canon_atom * dp_atoms
SpecialSymmetryAtomCompareFunctor()
const boost::dynamic_bitset * dp_bondsInPlay
const boost::dynamic_bitset * dp_atomsInPlay
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
unsigned int getNumAtoms() const
returns our number of atoms
CXXAtomIterator< const MolGraph, Atom *const, MolGraph::adjacency_iterator > atomNeighbors(Atom const *at) const
#define RDKIT_GRAPHMOL_EXPORT
void initFragmentCanonAtoms(const ROMol &mol, std::vector< Canon::canon_atom > &atoms, bool includeChirality, const std::vector< std::string > *atomSymbols, const std::vector< std::string > *bondSymbols, const boost::dynamic_bitset<> &atomsInPlay, const boost::dynamic_bitset<> &bondsInPlay, bool needsInit)
void rankWithFunctor(T &ftor, bool breakTies, int *order, bool useSpecial=false, bool useChirality=false, bool includeRingStereo=true, const boost::dynamic_bitset<> *atomsInPlay=nullptr, const boost::dynamic_bitset<> *bondsInPlay=nullptr)
RDKIT_GRAPHMOL_EXPORT void initCanonAtoms(const ROMol &mol, std::vector< Canon::canon_atom > &atoms, bool includeChirality=true, bool includeStereoGroups=true)
RDKIT_GRAPHMOL_EXPORT void CreateSinglePartition(unsigned int nAtoms, int *order, int *count, canon_atom *atoms)
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 chiralRankMolAtoms(const ROMol &mol, std::vector< unsigned int > &res)
RDKIT_GRAPHMOL_EXPORT void rankMolAtoms(const ROMol &mol, std::vector< unsigned int > &res, bool breakTies=true, bool includeChirality=true, bool includeIsotopes=true, bool includeAtomMaps=true, bool includeChiralPresence=false, bool includeStereoGroups=true, bool useNonStereoRanks=false, bool includeRingStereo=true)
Note that atom maps on dummy atoms will always be used.
RDKIT_GRAPHMOL_EXPORT void updateAtomNeighborIndex(canon_atom *atoms, std::vector< bondholder > &nbrs)
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, bool includeAtomMaps, bool includeChiralPresence, bool includeRingStereo=true)
Note that atom maps on dummy atoms will always be used.
RDKIT_RDGENERAL_EXPORT const std::string _CanonicalRankingNumber
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)
unsigned int countSwapsToInterconvert(const T &ref, T probe)
const std::string * p_symbol
static bool greater(const bondholder &lhs, const bondholder &rhs)
bool operator<(const bondholder &o) const
const canon_atom * controllingAtoms[4]
int compareStereo(const bondholder &o) const
bondholder(Bond::BondType bt, unsigned int bs, unsigned int ni, unsigned int nsc, unsigned int bidx)
bondholder(Bond::BondType bt, Bond::BondStereo bs, unsigned int ni, unsigned int nsc, unsigned int bidx)
static int compare(const bondholder &x, const bondholder &y, unsigned int div=1)
std::vector< bondholder > bonds
StereoGroupType typeOfStereoGroup
std::unique_ptr< int[]> nbrIds
std::vector< int > revistedNeighbors
std::vector< int > neighborNum
const std::string * p_symbol
unsigned int whichStereoGroup