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) {
120 canon_atom *atoms, std::vector<bondholder> &nbrs);
123 canon_atom *atoms, std::vector<bondholder> &nbrs,
unsigned int atomIdx,
124 std::vector<std::pair<unsigned int, unsigned int>> &result);
147 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
148 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
167 for (
unsigned int ii = 0;
176 std::vector<std::pair<unsigned int, unsigned int>> swapsi;
177 std::vector<std::pair<unsigned int, unsigned int>> swapsj;
185 for (
unsigned int ii = 0; ii < swapsi.size() && ii < swapsj.size(); ++ii) {
186 int cmp = swapsi[ii].second - swapsj[ii].second;
207 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
208 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
239 for (
unsigned int ii = 0;
258unsigned int getChiralRank(
const ROMol *dp_mol, canon_atom *dp_atoms,
260 unsigned int res = 0;
261 std::vector<unsigned int> perm;
262 perm.reserve(dp_atoms[i].atom->getDegree());
263 for (
const auto nbr : dp_mol->
atomNeighbors(dp_atoms[i].atom)) {
264 auto rnk = dp_atoms[nbr->getIdx()].index;
266 if (std::find(perm.begin(), perm.end(), rnk) != perm.end()) {
272 if (perm.size() == dp_atoms[i].atom->getDegree()) {
273 auto ctag = dp_atoms[i].atom->getChiralTag();
276 auto sortedPerm = perm;
277 std::sort(sortedPerm.begin(), sortedPerm.end());
281 res = res == 2 ? 1 : 2;
289 unsigned int getAtomRingNbrCode(
unsigned int i)
const {
294 auto nbrs =
dp_atoms[i].nbrIds.get();
295 unsigned int code = 0;
296 for (
unsigned j = 0; j <
dp_atoms[i].degree; ++j) {
297 if (
dp_atoms[nbrs[j]].isRingStereoAtom) {
298 code +=
dp_atoms[nbrs[j]].index * 10000 + 1;
304 int basecomp(
int i,
int j)
const {
305 unsigned int ivi, ivj;
312 }
else if (ivi > ivj) {
318 int rankingNumber_i = 0;
319 int rankingNumber_j = 0;
324 if (rankingNumber_i < rankingNumber_j) {
326 }
else if (rankingNumber_i > rankingNumber_j) {
333 int molAtomMapNumber_i = 0;
334 int molAtomMapNumber_j = 0;
345 if (molAtomMapNumber_i < molAtomMapNumber_j) {
347 }
else if (molAtomMapNumber_i > molAtomMapNumber_j) {
356 }
else if (ivi > ivj) {
370 ivi =
dp_atoms[i].atom->getAtomicNum();
371 ivj =
dp_atoms[j].atom->getAtomicNum();
374 }
else if (ivi > ivj) {
379 ivi =
dp_atoms[i].atom->getIsotope();
380 ivj =
dp_atoms[j].atom->getIsotope();
383 }
else if (ivi > ivj) {
393 }
else if (ivi > ivj) {
397 ivi =
dp_atoms[i].atom->getFormalCharge();
398 ivj =
dp_atoms[j].atom->getFormalCharge();
401 }
else if (ivi > ivj) {
412 }
else if (ivi > ivj) {
425 }
else if (ivj && !ivi) {
427 }
else if (ivi && ivj) {
428 auto iType =
dp_atoms[i].typeOfStereoGroup;
429 auto jType =
dp_atoms[j].typeOfStereoGroup;
432 }
else if (iType > jType) {
437 std::set<unsigned int> sgi;
438 for (
const auto sgat :
439 dp_mol->getStereoGroups()[ivi - 1].getAtoms()) {
440 sgi.insert(
dp_atoms[sgat->getIdx()].index);
442 std::set<unsigned int> sgj;
443 for (
const auto sgat :
444 dp_mol->getStereoGroups()[ivj - 1].getAtoms()) {
445 sgj.insert(
dp_atoms[sgat->getIdx()].index);
449 }
else if (sgi > sgj) {
458 }
else if (ivi > ivj) {
470 ivi =
dp_atoms[i].atom->getChiralTag() != 0;
471 ivj =
dp_atoms[j].atom->getChiralTag() != 0;
474 }
else if (ivi > ivj) {
487 }
else if (ivi > ivj) {
496 ivi = getAtomRingNbrCode(i);
497 ivj = getAtomRingNbrCode(j);
500 }
else if (ivi > ivj) {
523 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
524 const boost::dynamic_bitset<> *bondsInPlay =
nullptr)
534 int v = basecomp(i, j);
547 for (
unsigned int ii = 0;
574 void getAtomNeighborhood(std::vector<bondholder> &nbrs)
const {
575 for (
unsigned j = 0; j < nbrs.size(); ++j) {
576 unsigned int nbrIdx = nbrs[j].nbrIdx;
582 nbrs[j].nbrSymClass =
589 int basecomp(
int i,
int j)
const {
591 unsigned int ivi, ivj;
598 }
else if (ivi > ivj) {
603 ivi =
dp_atoms[i].atom->getAtomicNum();
604 ivj =
dp_atoms[j].atom->getAtomicNum();
607 }
else if (ivi > ivj) {
612 ivi =
dp_atoms[i].atom->getIsotope();
613 ivj =
dp_atoms[j].atom->getIsotope();
616 }
else if (ivi > ivj) {
626 ivi = cipCode ==
"R" ? 2 : 1;
630 ivj = cipCode ==
"R" ? 2 : 1;
634 }
else if (ivi > ivj) {
653 int v = basecomp(i, j);
659 getAtomNeighborhood(
dp_atoms[i].bonds);
660 getAtomNeighborhood(
dp_atoms[j].bonds);
665 for (
unsigned int ii = 0;
674 for (
unsigned int ii = 0;
698template <
typename CompareFunc>
700 int mode, std::vector<int> &order,
701 std::vector<int> &count,
int &activeset,
702 std::vector<int> &next, std::vector<int> &changed,
703 std::vector<char> &touchedPartitions) {
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);
743 hanoisort(start, count, changed, compar);
750 for (
int k = 0; k < len; ++k) {
751 changed[start[k]] = 0;
757 for (i = count[index]; i < len; i++) {
760 symclass = offset + i;
762 atoms[index].
index = symclass;
767 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
768 changed[atoms[index].
nbrIds[j]] = 1;
775 for (i = count[index]; i < len; i++) {
777 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
778 unsigned int nbor = atoms[index].
nbrIds[j];
779 touchedPartitions[atoms[nbor].
index] = 1;
782 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
783 if (touchedPartitions[ii]) {
784 partition = order[ii];
785 if ((count[partition] > 1) && (next[partition] == -2)) {
786 next[partition] = activeset;
787 activeset = partition;
789 touchedPartitions[ii] = 0;
796template <
typename CompareFunc>
798 int mode, std::vector<int> &order, std::vector<int> &count,
799 int &activeset, std::vector<int> &next,
800 std::vector<int> &changed,
801 std::vector<char> &touchedPartitions) {
809 for (
unsigned int i = 0; i < nAtoms; i++) {
810 partition = order[i];
811 oldPart = atoms[partition].
index;
812 while (count[partition] > 1) {
813 len = count[partition];
814 offset = atoms[partition].
index + len - 1;
815 index = order[offset];
816 atoms[index].
index = offset;
817 count[partition] = len - 1;
821 if (atoms[index].degree < 1) {
824 for (
unsigned j = 0; j < atoms[index].
degree; ++j) {
825 unsigned int nbor = atoms[index].
nbrIds[j];
826 touchedPartitions[atoms[nbor].
index] = 1;
830 for (
unsigned int ii = 0; ii < nAtoms; ++ii) {
831 if (touchedPartitions[ii]) {
832 int npart = order[ii];
833 if ((count[npart] > 1) && (next[npart] == -2)) {
834 next[npart] = activeset;
837 touchedPartitions[ii] = 0;
841 changed, touchedPartitions);
844 if (atoms[partition].index != oldPart) {
851 std::vector<int> &order,
852 std::vector<int> &count,
856 unsigned int nAtoms, std::vector<int> &order, std::vector<int> &count,
857 int &activeset, std::vector<int> &next, std::vector<int> &changed);
861 const ROMol &mol, std::vector<unsigned int> &res,
bool breakTies =
true,
862 bool includeChirality =
true,
bool includeIsotopes =
true,
863 bool includeAtomMaps =
true,
bool includeChiralPresence =
false,
864 bool includeStereoGroups =
true,
bool useNonStereoRanks =
false,
865 bool includeRingStereo =
true);
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,
873 const std::vector<std::string> *bondSymbols,
bool breakTies,
874 bool includeChirality,
bool includeIsotope,
bool includeAtomMaps,
875 bool includeChiralPresence,
bool includeRingStereo =
true);
879 const ROMol &mol, std::vector<unsigned int> &res,
880 const boost::dynamic_bitset<> &atomsInPlay,
881 const boost::dynamic_bitset<> &bondsInPlay,
882 const std::vector<std::string> *atomSymbols =
nullptr,
883 bool breakTies =
true,
bool includeChirality =
true,
884 bool includeIsotopes =
true,
bool includeAtomMaps =
true,
885 bool includeChiralPresence =
false,
bool includeRingStereo =
true) {
887 breakTies, includeChirality, includeIsotopes,
888 includeAtomMaps, includeChiralPresence, includeRingStereo);
892 std::vector<unsigned int> &res);
895 std::vector<Canon::canon_atom> &atoms,
896 bool includeChirality =
true,
897 bool includeStereoGroups =
true);
901 std::vector<Canon::canon_atom> &atoms,
902 bool includeChirality,
903 const std::vector<std::string> *atomSymbols,
904 const std::vector<std::string> *bondSymbols,
905 const boost::dynamic_bitset<> &atomsInPlay,
906 const boost::dynamic_bitset<> &bondsInPlay,
910 bool useSpecial =
false,
bool useChirality =
false,
911 bool includeRingStereo =
true,
912 const boost::dynamic_bitset<> *atomsInPlay =
nullptr,
913 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