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, std::vector<int> &order,
698 std::vector<int> &count,
int &activeset,
699 std::vector<int> &next, std::vector<int> &changed,
700 std::vector<char> &touchedPartitions) {
711 while (activeset != -1) {
723 partition = activeset;
724 activeset = next[partition];
725 next[partition] = -2;
727 len = count[partition];
728 offset = atoms[partition].
index;
729 auto start = std::span<int>(&order[offset], len);
740 hanoisort(start, count, changed, compar);
747 for (
int k = 0; k < len; ++k) {
748 changed[start[k]] = 0;
754 for (i = count[index]; i < len; i++) {
757 symclass = offset + i;
759 atoms[index].
index = symclass;
764 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
765 changed[atoms[index].
nbrIds[j]] = 1;
772 for (i = count[index]; i < len; i++) {
774 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
775 unsigned int nbor = atoms[index].
nbrIds[j];
776 touchedPartitions[atoms[nbor].
index] = 1;
779 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
780 if (touchedPartitions[ii]) {
781 partition = order[ii];
782 if ((count[partition] > 1) && (next[partition] == -2)) {
783 next[partition] = activeset;
784 activeset = partition;
786 touchedPartitions[ii] = 0;
793template <
typename CompareFunc>
795 int mode, std::vector<int> &order, std::vector<int> &count,
796 int &activeset, std::vector<int> &next,
797 std::vector<int> &changed,
798 std::vector<char> &touchedPartitions) {
806 for (
unsigned int i = 0; i < nAtoms; i++) {
807 partition = order[i];
808 oldPart = atoms[partition].
index;
809 while (count[partition] > 1) {
810 len = count[partition];
811 offset = atoms[partition].
index + len - 1;
812 index = order[offset];
813 atoms[index].
index = offset;
814 count[partition] = len - 1;
818 if (atoms[index].degree < 1) {
821 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
822 unsigned int nbor = atoms[index].
nbrIds[j];
823 touchedPartitions[atoms[nbor].
index] = 1;
827 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
828 if (touchedPartitions[ii]) {
829 int npart = order[ii];
830 if ((count[npart] > 1) && (next[npart] == -2)) {
831 next[npart] = activeset;
834 touchedPartitions[ii] = 0;
838 changed, touchedPartitions);
841 if (atoms[partition].index != oldPart) {
848 std::vector<int> &order,
849 std::vector<int> &count,
853 unsigned int nAtoms, std::vector<int> &order, std::vector<int> &count,
854 int &activeset, std::vector<int> &next, std::vector<int> &changed);
858 const ROMol &mol, std::vector<unsigned int> &res,
bool breakTies =
true,
859 bool includeChirality =
true,
bool includeIsotopes =
true,
860 bool includeAtomMaps =
true,
bool includeChiralPresence =
false,
861 bool includeStereoGroups =
true,
bool useNonStereoRanks =
false,
862 bool includeRingStereo =
true);
866 const ROMol &mol, std::vector<unsigned int> &res,
867 const boost::dynamic_bitset<> &atomsInPlay,
868 const boost::dynamic_bitset<> &bondsInPlay,
869 const std::vector<std::string> *atomSymbols,
870 const std::vector<std::string> *bondSymbols,
bool breakTies,
871 bool includeChirality,
bool includeIsotope,
bool includeAtomMaps,
872 bool includeChiralPresence,
bool includeRingStereo =
true);
876 const ROMol &mol, std::vector<unsigned int> &res,
877 const boost::dynamic_bitset<> &atomsInPlay,
878 const boost::dynamic_bitset<> &bondsInPlay,
879 const std::vector<std::string> *atomSymbols =
nullptr,
880 bool breakTies =
true,
bool includeChirality =
true,
881 bool includeIsotopes =
true,
bool includeAtomMaps =
true,
882 bool includeChiralPresence =
false,
bool includeRingStereo =
true) {
884 breakTies, includeChirality, includeIsotopes,
885 includeAtomMaps, includeChiralPresence, includeRingStereo);
889 std::vector<unsigned int> &res);
892 std::vector<Canon::canon_atom> &atoms,
893 bool includeChirality =
true,
894 bool includeStereoGroups =
true);
898 std::vector<Canon::canon_atom> &atoms,
899 bool includeChirality,
900 const std::vector<std::string> *atomSymbols,
901 const std::vector<std::string> *bondSymbols,
902 const boost::dynamic_bitset<> &atomsInPlay,
903 const boost::dynamic_bitset<> &bondsInPlay,
907 bool useSpecial =
false,
bool useChirality =
false,
908 bool includeRingStereo =
true,
909 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
910 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)
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)
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)
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)
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
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