19#include <boost/dynamic_bitset.hpp>
47 unsigned int nsc,
unsigned int bidx)
54 unsigned int nsc,
unsigned int bidx)
69 unsigned int div = 1) {
118 canon_atom *atoms, std::vector<bondholder> &nbrs);
121 canon_atom *atoms, std::vector<bondholder> &nbrs,
unsigned int atomIdx,
122 std::vector<std::pair<unsigned int, unsigned int>> &result);
145 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
146 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
165 for (
unsigned int ii = 0;
174 std::vector<std::pair<unsigned int, unsigned int>> swapsi;
175 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;
202 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
203 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
234 for (
unsigned int ii = 0;
253unsigned int getChiralRank(
const ROMol *dp_mol, canon_atom *dp_atoms,
255 unsigned int res = 0;
256 std::vector<unsigned int> perm;
257 perm.reserve(dp_atoms[i].atom->getDegree());
258 for (
const auto nbr : dp_mol->
atomNeighbors(dp_atoms[i].atom)) {
259 auto rnk = dp_atoms[nbr->getIdx()].index;
261 if (std::find(perm.begin(), perm.end(), rnk) != perm.end()) {
267 if (perm.size() == dp_atoms[i].atom->getDegree()) {
268 auto ctag = dp_atoms[i].atom->getChiralTag();
271 auto sortedPerm = perm;
272 std::sort(sortedPerm.begin(), sortedPerm.end());
276 res = res == 2 ? 1 : 2;
284 unsigned int getAtomRingNbrCode(
unsigned int i)
const {
289 auto nbrs =
dp_atoms[i].nbrIds.get();
290 unsigned int code = 0;
291 for (
unsigned j = 0; j <
dp_atoms[i].degree; ++j) {
292 if (
dp_atoms[nbrs[j]].isRingStereoAtom) {
293 code +=
dp_atoms[nbrs[j]].index * 10000 + 1;
299 int basecomp(
int i,
int j)
const {
300 unsigned int ivi, ivj;
307 }
else if (ivi > ivj) {
313 int rankingNumber_i = 0;
314 int rankingNumber_j = 0;
319 if (rankingNumber_i < rankingNumber_j) {
321 }
else if (rankingNumber_i > rankingNumber_j) {
328 int molAtomMapNumber_i = 0;
329 int molAtomMapNumber_j = 0;
340 if (molAtomMapNumber_i < molAtomMapNumber_j) {
342 }
else if (molAtomMapNumber_i > molAtomMapNumber_j) {
351 }
else if (ivi > ivj) {
365 ivi =
dp_atoms[i].atom->getAtomicNum();
366 ivj =
dp_atoms[j].atom->getAtomicNum();
369 }
else if (ivi > ivj) {
374 ivi =
dp_atoms[i].atom->getIsotope();
375 ivj =
dp_atoms[j].atom->getIsotope();
378 }
else if (ivi > ivj) {
388 }
else if (ivi > ivj) {
392 ivi =
dp_atoms[i].atom->getFormalCharge();
393 ivj =
dp_atoms[j].atom->getFormalCharge();
396 }
else if (ivi > ivj) {
407 }
else if (ivi > ivj) {
420 }
else if (ivj && !ivi) {
422 }
else if (ivi && ivj) {
423 auto iType =
dp_atoms[i].typeOfStereoGroup;
424 auto jType =
dp_atoms[j].typeOfStereoGroup;
427 }
else if (iType > jType) {
432 std::set<unsigned int> sgi;
433 for (
const auto sgat :
434 dp_mol->getStereoGroups()[ivi - 1].getAtoms()) {
435 sgi.insert(
dp_atoms[sgat->getIdx()].index);
437 std::set<unsigned int> sgj;
438 for (
const auto sgat :
439 dp_mol->getStereoGroups()[ivj - 1].getAtoms()) {
440 sgj.insert(
dp_atoms[sgat->getIdx()].index);
444 }
else if (sgi > sgj) {
453 }
else if (ivi > ivj) {
465 ivi =
dp_atoms[i].atom->getChiralTag() != 0;
466 ivj =
dp_atoms[j].atom->getChiralTag() != 0;
469 }
else if (ivi > ivj) {
482 }
else if (ivi > ivj) {
491 ivi = getAtomRingNbrCode(i);
492 ivj = getAtomRingNbrCode(j);
495 }
else if (ivi > ivj) {
518 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
519 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
529 int v = basecomp(i, j);
542 for (
unsigned int ii = 0;
569 void getAtomNeighborhood(std::vector<bondholder> &nbrs)
const {
570 for (
unsigned j = 0; j < nbrs.size(); ++j) {
571 unsigned int nbrIdx = nbrs[j].nbrIdx;
577 nbrs[j].nbrSymClass =
584 int basecomp(
int i,
int j)
const {
586 unsigned int ivi, ivj;
593 }
else if (ivi > ivj) {
598 ivi =
dp_atoms[i].atom->getAtomicNum();
599 ivj =
dp_atoms[j].atom->getAtomicNum();
602 }
else if (ivi > ivj) {
607 ivi =
dp_atoms[i].atom->getIsotope();
608 ivj =
dp_atoms[j].atom->getIsotope();
611 }
else if (ivi > ivj) {
621 ivi = cipCode ==
"R" ? 2 : 1;
625 ivj = cipCode ==
"R" ? 2 : 1;
629 }
else if (ivi > ivj) {
648 int v = basecomp(i, j);
654 getAtomNeighborhood(
dp_atoms[i].bonds);
655 getAtomNeighborhood(
dp_atoms[j].bonds);
660 for (
unsigned int ii = 0;
669 for (
unsigned int ii = 0;
693template <
typename CompareFunc>
695 int mode,
int *order,
int *count,
int &activeset,
696 int *next,
int *changed,
char *touchedPartitions) {
708 while (activeset != -1) {
720 partition = activeset;
721 activeset = next[partition];
722 next[partition] = -2;
724 len = count[partition];
725 offset = atoms[partition].
index;
726 start = order + offset;
737 hanoisort(start, len, count, changed, compar);
744 for (
int k = 0; k < len; ++k) {
745 changed[start[k]] = 0;
751 for (i = count[index]; i < len; i++) {
754 symclass = offset + i;
756 atoms[index].
index = symclass;
761 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
762 changed[atoms[index].
nbrIds[j]] = 1;
769 for (i = count[index]; i < len; i++) {
771 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
772 unsigned int nbor = atoms[index].
nbrIds[j];
773 touchedPartitions[atoms[nbor].
index] = 1;
776 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
777 if (touchedPartitions[ii]) {
778 partition = order[ii];
779 if ((count[partition] > 1) && (next[partition] == -2)) {
780 next[partition] = activeset;
781 activeset = partition;
783 touchedPartitions[ii] = 0;
790template <
typename CompareFunc>
792 int mode,
int *order,
int *count,
int &activeset,
int *next,
793 int *changed,
char *touchedPartitions) {
801 for (
unsigned int i = 0; i < nAtoms; i++) {
802 partition = order[i];
803 oldPart = atoms[partition].
index;
804 while (count[partition] > 1) {
805 len = count[partition];
806 offset = atoms[partition].
index + len - 1;
807 index = order[offset];
808 atoms[index].
index = offset;
809 count[partition] = len - 1;
813 if (atoms[index].degree < 1) {
816 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
817 unsigned int nbor = atoms[index].
nbrIds[j];
818 touchedPartitions[atoms[nbor].
index] = 1;
822 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
823 if (touchedPartitions[ii]) {
824 int npart = order[ii];
825 if ((count[npart] > 1) && (next[npart] == -2)) {
826 next[npart] = activeset;
829 touchedPartitions[ii] = 0;
833 changed, touchedPartitions);
836 if (atoms[partition].index != oldPart) {
843 int *order,
int *count,
847 int *count,
int &activeset,
848 int *next,
int *changed);
852 const ROMol &mol, std::vector<unsigned int> &res,
bool breakTies =
true,
853 bool includeChirality =
true,
bool includeIsotopes =
true,
854 bool includeAtomMaps =
true,
bool includeChiralPresence =
false,
855 bool includeStereoGroups =
true,
bool useNonStereoRanks =
false);
859 const ROMol &mol, std::vector<unsigned int> &res,
860 const boost::dynamic_bitset<> &atomsInPlay,
861 const boost::dynamic_bitset<> &bondsInPlay,
862 const std::vector<std::string> *atomSymbols,
863 const std::vector<std::string> *bondSymbols,
bool breakTies,
864 bool includeChirality,
bool includeIsotope,
bool includeAtomMaps,
865 bool includeChiralPresence);
869 const ROMol &mol, std::vector<unsigned int> &res,
870 const boost::dynamic_bitset<> &atomsInPlay,
871 const boost::dynamic_bitset<> &bondsInPlay,
872 const std::vector<std::string> *atomSymbols =
nullptr,
873 bool breakTies =
true,
bool includeChirality =
true,
874 bool includeIsotopes =
true,
bool includeAtomMaps =
true,
875 bool includeChiralPresence =
false) {
877 breakTies, includeChirality, includeIsotopes,
878 includeAtomMaps, includeChiralPresence);
882 std::vector<unsigned int> &res);
885 std::vector<Canon::canon_atom> &atoms,
886 bool includeChirality =
true,
887 bool includeStereoGroups =
true);
891 std::vector<Canon::canon_atom> &atoms,
892 bool includeChirality,
893 const std::vector<std::string> *atomSymbols,
894 const std::vector<std::string> *bondSymbols,
895 const boost::dynamic_bitset<> &atomsInPlay,
896 const boost::dynamic_bitset<> &bondsInPlay,
900 bool useSpecial =
false,
bool useChirality =
false,
901 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
902 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 rankWithFunctor(T &ftor, bool breakTies, int *order, bool useSpecial=false, bool useChirality=false, const boost::dynamic_bitset<> *atomsInPlay=nullptr, const boost::dynamic_bitset<> *bondsInPlay=nullptr)
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)
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 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)
Note that atom maps on dummy atoms will always be used.
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)
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)
Note that atom maps on dummy atoms will always be used.
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 updateAtomNeighborIndex(canon_atom *atoms, std::vector< bondholder > &nbrs)
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