22#include <boost/dynamic_bitset.hpp>
49 unsigned int nsc,
unsigned int bidx)
56 unsigned int nsc,
unsigned int bidx)
71 unsigned int div = 1) {
74 if (symbolCompare != 0) {
119 canon_atom *atoms, std::vector<bondholder> &nbrs);
122 canon_atom *atoms, std::vector<bondholder> &nbrs,
unsigned int atomIdx,
123 std::vector<std::pair<unsigned int, unsigned int>> &result);
146 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
147 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
166 for (
unsigned int ii = 0;
175 std::vector<std::pair<unsigned int, unsigned int>> swapsi;
176 std::vector<std::pair<unsigned int, unsigned int>> swapsj;
184 for (
unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) {
185 int cmp = swapsi[ii].second - swapsj[ii].second;
206 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
207 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
238 for (
unsigned int ii = 0;
257unsigned int getChiralRank(
const ROMol *dp_mol, canon_atom *dp_atoms,
259 unsigned int res = 0;
260 std::vector<unsigned int> perm;
261 perm.reserve(dp_atoms[i].atom->getDegree());
262 for (
const auto nbr : dp_mol->
atomNeighbors(dp_atoms[i].atom)) {
263 auto rnk = dp_atoms[nbr->getIdx()].index;
265 if (std::find(perm.begin(), perm.end(), rnk) != perm.end()) {
271 if (perm.size() == dp_atoms[i].atom->getDegree()) {
272 auto ctag = dp_atoms[i].atom->getChiralTag();
275 auto sortedPerm = perm;
276 std::sort(sortedPerm.begin(), sortedPerm.end());
280 res = res == 2 ? 1 : 2;
288 unsigned int getAtomRingNbrCode(
unsigned int i)
const {
293 auto nbrs =
dp_atoms[i].nbrIds.get();
294 unsigned int code = 0;
295 for (
unsigned j = 0; j <
dp_atoms[i].degree; ++j) {
296 if (
dp_atoms[nbrs[j]].isRingStereoAtom) {
297 code +=
dp_atoms[nbrs[j]].index * 10000 + 1;
303 int basecomp(
int i,
int j)
const {
304 unsigned int ivi, ivj;
311 }
else if (ivi > ivj) {
317 int rankingNumber_i = 0;
318 int rankingNumber_j = 0;
323 if (rankingNumber_i < rankingNumber_j) {
325 }
else if (rankingNumber_i > rankingNumber_j) {
332 int molAtomMapNumber_i = 0;
333 int molAtomMapNumber_j = 0;
344 if (molAtomMapNumber_i < molAtomMapNumber_j) {
346 }
else if (molAtomMapNumber_i > molAtomMapNumber_j) {
355 }
else if (ivi > ivj) {
363 ivi =
dp_atoms[i].atom->getAtomicNum();
364 ivj =
dp_atoms[j].atom->getAtomicNum();
367 }
else if (ivi > ivj) {
372 ivi =
dp_atoms[i].atom->getIsotope();
373 ivj =
dp_atoms[j].atom->getIsotope();
376 }
else if (ivi > ivj) {
386 }
else if (ivi > ivj) {
390 ivi =
dp_atoms[i].atom->getFormalCharge();
391 ivj =
dp_atoms[j].atom->getFormalCharge();
394 }
else if (ivi > ivj) {
405 }
else if (ivi > ivj) {
418 }
else if (ivj && !ivi) {
420 }
else if (ivi && ivj) {
421 auto iType =
dp_atoms[i].typeOfStereoGroup;
422 auto jType =
dp_atoms[j].typeOfStereoGroup;
425 }
else if (iType > jType) {
430 std::set<unsigned int> sgi;
431 for (
const auto sgat :
432 dp_mol->getStereoGroups()[ivi - 1].getAtoms()) {
433 sgi.insert(
dp_atoms[sgat->getIdx()].index);
435 std::set<unsigned int> sgj;
436 for (
const auto sgat :
437 dp_mol->getStereoGroups()[ivj - 1].getAtoms()) {
438 sgj.insert(
dp_atoms[sgat->getIdx()].index);
442 }
else if (sgi > sgj) {
451 }
else if (ivi > ivj) {
463 ivi =
dp_atoms[i].atom->getChiralTag() != 0;
464 ivj =
dp_atoms[j].atom->getChiralTag() != 0;
467 }
else if (ivi > ivj) {
480 }
else if (ivi > ivj) {
489 ivi = getAtomRingNbrCode(i);
490 ivj = getAtomRingNbrCode(j);
493 }
else if (ivi > ivj) {
516 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
517 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
527 int v = basecomp(i, j);
540 for (
unsigned int ii = 0;
567 void getAtomNeighborhood(std::vector<bondholder> &nbrs)
const {
568 for (
unsigned j = 0; j < nbrs.size(); ++j) {
569 unsigned int nbrIdx = nbrs[j].nbrIdx;
575 nbrs[j].nbrSymClass =
582 int basecomp(
int i,
int j)
const {
584 unsigned int ivi, ivj;
591 }
else if (ivi > ivj) {
596 ivi =
dp_atoms[i].atom->getAtomicNum();
597 ivj =
dp_atoms[j].atom->getAtomicNum();
600 }
else if (ivi > ivj) {
605 ivi =
dp_atoms[i].atom->getIsotope();
606 ivj =
dp_atoms[j].atom->getIsotope();
609 }
else if (ivi > ivj) {
619 ivi = cipCode ==
"R" ? 2 : 1;
623 ivj = cipCode ==
"R" ? 2 : 1;
627 }
else if (ivi > ivj) {
646 int v = basecomp(i, j);
652 getAtomNeighborhood(
dp_atoms[i].bonds);
653 getAtomNeighborhood(
dp_atoms[j].bonds);
658 for (
unsigned int ii = 0;
667 for (
unsigned int ii = 0;
691template <
typename CompareFunc>
693 int mode, std::vector<int> &order,
694 std::vector<int> &count,
int &activeset,
695 std::vector<int> &next, std::vector<int> &changed,
696 std::vector<char> &touchedPartitions,
697 std::vector<int> *hanoiTemp =
nullptr) {
699 std::vector<int> localHanoiTemp;
701 localHanoiTemp.resize(nAtoms);
702 hanoiTemp = &localHanoiTemp;
710 PRECONDITION(hanoiTemp->size() >= nAtoms,
"hanoi scratch is too small");
714 while (activeset != -1) {
726 partition = activeset;
727 activeset = next[partition];
728 next[partition] = -2;
730 len = count[partition];
731 offset = atoms[partition].
index;
732 auto start = std::span<int>(&order[offset], len);
744 changed.data(), compar)) {
745 std::copy_n(hanoiTemp->begin(), len, start.begin());
753 for (
int k = 0; k < len; ++k) {
754 changed[start[k]] = 0;
760 for (i = count[index]; i < len; i++) {
763 symclass = offset + i;
765 atoms[index].
index = symclass;
770 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
771 changed[atoms[index].
nbrIds[j]] = 1;
778 for (i = count[index]; i < len; i++) {
780 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
781 unsigned int nbor = atoms[index].
nbrIds[j];
782 touchedPartitions[atoms[nbor].
index] = 1;
785 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
786 if (touchedPartitions[ii]) {
787 partition = order[ii];
788 if ((count[partition] > 1) && (next[partition] == -2)) {
789 next[partition] = activeset;
790 activeset = partition;
792 touchedPartitions[ii] = 0;
799template <
typename CompareFunc>
801 int mode, std::vector<int> &order, std::vector<int> &count,
802 int &activeset, std::vector<int> &next,
803 std::vector<int> &changed,
804 std::vector<char> &touchedPartitions,
805 std::vector<int> *hanoiTemp =
nullptr) {
813 for (
unsigned int i = 0; i < nAtoms; i++) {
814 partition = order[i];
815 oldPart = atoms[partition].
index;
816 while (count[partition] > 1) {
817 len = count[partition];
818 offset = atoms[partition].
index + len - 1;
819 index = order[offset];
820 atoms[index].
index = offset;
821 count[partition] = len - 1;
825 if (atoms[index].degree < 1) {
828 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
829 unsigned int nbor = atoms[index].
nbrIds[j];
830 touchedPartitions[atoms[nbor].
index] = 1;
834 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
835 if (touchedPartitions[ii]) {
836 int npart = order[ii];
837 if ((count[npart] > 1) && (next[npart] == -2)) {
838 next[npart] = activeset;
841 touchedPartitions[ii] = 0;
845 changed, touchedPartitions, hanoiTemp);
848 if (atoms[partition].index != oldPart) {
855 std::vector<int> &order,
856 std::vector<int> &count,
860 unsigned int nAtoms, std::vector<int> &order, std::vector<int> &count,
861 int &activeset, std::vector<int> &next, std::vector<int> &changed);
865 const ROMol &mol, std::vector<unsigned int> &res,
bool breakTies =
true,
866 bool includeChirality =
true,
bool includeIsotopes =
true,
867 bool includeAtomMaps =
true,
bool includeChiralPresence =
false,
868 bool includeStereoGroups =
true,
bool useNonStereoRanks =
false,
869 bool includeRingStereo =
true);
873 const ROMol &mol, std::vector<unsigned int> &res,
874 const boost::dynamic_bitset<> &atomsInPlay,
875 const boost::dynamic_bitset<> &bondsInPlay,
876 const std::vector<std::string> *atomSymbols,
877 const std::vector<std::string> *bondSymbols,
bool breakTies,
878 bool includeChirality,
bool includeIsotope,
bool includeAtomMaps,
879 bool includeChiralPresence,
bool includeRingStereo =
true);
883 const ROMol &mol, std::vector<unsigned int> &res,
884 const boost::dynamic_bitset<> &atomsInPlay,
885 const boost::dynamic_bitset<> &bondsInPlay,
886 const std::vector<std::string> *atomSymbols =
nullptr,
887 bool breakTies =
true,
bool includeChirality =
true,
888 bool includeIsotopes =
true,
bool includeAtomMaps =
true,
889 bool includeChiralPresence =
false,
bool includeRingStereo =
true) {
891 breakTies, includeChirality, includeIsotopes,
892 includeAtomMaps, includeChiralPresence, includeRingStereo);
896 std::vector<unsigned int> &res);
899 std::vector<Canon::canon_atom> &atoms,
900 bool includeChirality =
true,
901 bool includeStereoGroups =
true);
905 std::vector<Canon::canon_atom> &atoms,
906 bool includeChirality,
907 const std::vector<std::string> *atomSymbols,
908 const std::vector<std::string> *bondSymbols,
909 const boost::dynamic_bitset<> &atomsInPlay,
910 const boost::dynamic_bitset<> &bondsInPlay,
914 bool useSpecial =
false,
bool useChirality =
false,
915 bool includeRingStereo =
true,
916 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
917 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, std::vector< int > &order, bool useSpecial=false, bool useChirality=false, bool includeRingStereo=true, 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)
void RefinePartitions(const ROMol &mol, canon_atom *atoms, CompareFunc compar, int mode, std::vector< int > &order, std::vector< int > &count, int &activeset, std::vector< int > &next, std::vector< int > &changed, std::vector< char > &touchedPartitions, std::vector< int > *hanoiTemp=nullptr)
const unsigned int ATNUM_CLASS_OFFSET
RDKIT_GRAPHMOL_EXPORT void CreateSinglePartition(unsigned int nAtoms, std::vector< int > &order, std::vector< int > &count, canon_atom *atoms)
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_GRAPHMOL_EXPORT void ActivatePartitions(unsigned int nAtoms, std::vector< int > &order, std::vector< int > &count, int &activeset, std::vector< int > &next, std::vector< int > &changed)
void BreakTies(const ROMol &mol, canon_atom *atoms, CompareFunc compar, int mode, std::vector< int > &order, std::vector< int > &count, int &activeset, std::vector< int > &next, std::vector< int > &changed, std::vector< char > &touchedPartitions, std::vector< int > *hanoiTemp=nullptr)
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.
constexpr std::string_view _CanonicalRankingNumber
constexpr std::string_view _CIPCode
constexpr std::string_view molAtomMapNumber
bool hanoi(int *base, int nel, int *temp, 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