15 #include <boost/cstdint.hpp> 16 #include <boost/foreach.hpp> 17 #include <boost/dynamic_bitset.hpp> 35 bondStereo(static_cast<unsigned int>(
Bond::STEREONONE)),
36 nbrIdx(0), nbrSymClass(0){};
39 bondStereo(static_cast<unsigned int>(bs)),
88 canon_atom() : atom(NULL),index(-1),degree(0),totalNumHs(0),
89 hasRingNbr(false), isRingStereoAtom(false), nbrIds(NULL),
90 p_symbol(NULL), neighborNum(0), revistedNeighbors(0) {};
96 unsigned int atomIdx, std::vector<std::pair<unsigned int, unsigned int> >& result);
114 dp_atomsInPlay(NULL), dp_bondsInPlay(NULL) {
117 const boost::dynamic_bitset<> *atomsInPlay=NULL,
118 const boost::dynamic_bitset<> *bondsInPlay=NULL ) :
119 dp_atoms(atoms), dp_mol(&m),
120 dp_atomsInPlay(atomsInPlay),dp_bondsInPlay(bondsInPlay) {
126 if(dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])){
130 if((dp_atomsInPlay && (*dp_atomsInPlay)[i]) || !dp_atomsInPlay){
133 if((dp_atomsInPlay && (*dp_atomsInPlay)[j]) || !dp_atomsInPlay){
136 for(
unsigned int ii=0;ii<dp_atoms[i].
bonds.size() && ii<dp_atoms[j].
bonds.size();++ii){
141 std::vector<std::pair<unsigned int, unsigned int> > swapsi;
142 std::vector<std::pair<unsigned int, unsigned int> > swapsj;
143 if((dp_atomsInPlay && (*dp_atomsInPlay)[i]) || !dp_atomsInPlay){
146 if((dp_atomsInPlay && (*dp_atomsInPlay)[j]) || !dp_atomsInPlay){
149 for(
unsigned int ii=0;ii<swapsi.size() && ii<swapsj.size();++ii){
150 int cmp=swapsi[ii].second-swapsj[ii].second;
165 dp_atomsInPlay(NULL), dp_bondsInPlay(NULL) {
168 const boost::dynamic_bitset<> *atomsInPlay=NULL,
169 const boost::dynamic_bitset<> *bondsInPlay=NULL ) :
170 dp_atoms(atoms), dp_mol(&m),
171 dp_atomsInPlay(atomsInPlay),dp_bondsInPlay(bondsInPlay) {
177 if(dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])){
181 if(dp_atoms[i].neighborNum < dp_atoms[j].neighborNum){
184 else if(dp_atoms[i].neighborNum > dp_atoms[j].neighborNum){
188 if(dp_atoms[i].revistedNeighbors < dp_atoms[j].revistedNeighbors){
191 else if(dp_atoms[i].revistedNeighbors > dp_atoms[j].revistedNeighbors){
195 if((dp_atomsInPlay && (*dp_atomsInPlay)[i]) || !dp_atomsInPlay){
198 if((dp_atomsInPlay && (*dp_atomsInPlay)[j]) || !dp_atomsInPlay){
201 for(
unsigned int ii=0;ii<dp_atoms[i].
bonds.size() && ii<dp_atoms[j].
bonds.size();++ii){
206 if(dp_atoms[i].bonds.size()<dp_atoms[j].
bonds.size()){
208 }
else if(dp_atoms[i].bonds.size()>dp_atoms[j].
bonds.size()) {
217 unsigned int getAtomRingNbrCode(
unsigned int i)
const {
218 if(!dp_atoms[i].hasRingNbr)
return 0;
220 const Atom *at=dp_atoms[i].atom;
221 int *nbrs = dp_atoms[i].nbrIds;
223 for(
unsigned j=0; j<dp_atoms[i].degree; ++j){
224 if(dp_atoms[nbrs[j]].isRingStereoAtom){
226 code += dp_atoms[nbrs[j]].index*10000+1;
232 int basecomp(
int i,
int j)
const {
234 unsigned int ivi,ivj;
237 ivi= dp_atoms[i].index;
238 ivj= dp_atoms[j].index;
245 std::string molAtomMapNumber_i=
"";
246 std::string molAtomMapNumber_j=
"";
249 if(molAtomMapNumber_i<molAtomMapNumber_j)
251 else if(molAtomMapNumber_i>molAtomMapNumber_j)
255 ivi= dp_atoms[i].degree;
256 ivj= dp_atoms[j].degree;
262 if(dp_atoms[i].p_symbol &&
263 dp_atoms[j].p_symbol ) {
264 if( *(dp_atoms[i].p_symbol) < *(dp_atoms[j].p_symbol) )
266 else if( *(dp_atoms[i].p_symbol) > *(dp_atoms[j].p_symbol) )
272 ivi= dp_atoms[i].atom->getAtomicNum();
273 ivj= dp_atoms[j].atom->getAtomicNum();
281 ivi=dp_atoms[i].atom->getIsotope();
282 ivj=dp_atoms[j].atom->getIsotope();
290 ivi=dp_atoms[i].totalNumHs;
291 ivj=dp_atoms[j].totalNumHs;
298 ivi=dp_atoms[i].atom->getFormalCharge();
299 ivj=dp_atoms[j].atom->getFormalCharge();
312 ivi=cipCode==
"R"?2:1;
315 ivj=cipCode==
"R"?2:1;
323 ivi=dp_atoms[i].atom->getChiralTag()!=0;
324 ivj=dp_atoms[j].atom->getChiralTag()!=0;
331 if(df_useChiralityRings){
333 ivi=getAtomRingNbrCode(i);
334 ivj=getAtomRingNbrCode(j);
353 dp_atomsInPlay(NULL), dp_bondsInPlay(NULL),
355 df_useIsotopes(true), df_useChirality(true), df_useChiralityRings(true) {
358 const boost::dynamic_bitset<> *atomsInPlay=NULL,
359 const boost::dynamic_bitset<> *bondsInPlay=NULL ) :
360 dp_atoms(atoms), dp_mol(&m),
361 dp_atomsInPlay(atomsInPlay),dp_bondsInPlay(bondsInPlay),
362 df_useNbrs(false),df_useIsotopes(true), df_useChirality(true), df_useChiralityRings(true) {
368 if(dp_atomsInPlay && !((*dp_atomsInPlay)[i] || (*dp_atomsInPlay)[j])){
378 if((dp_atomsInPlay && (*dp_atomsInPlay)[i]) || !dp_atomsInPlay){
381 if((dp_atomsInPlay && (*dp_atomsInPlay)[j]) || !dp_atomsInPlay){
385 for(
unsigned int ii=0;ii<dp_atoms[i].
bonds.size() && ii<dp_atoms[j].
bonds.size();++ii){
390 if(dp_atoms[i].bonds.size()<dp_atoms[j].
bonds.size()){
392 }
else if(dp_atoms[i].bonds.size()>dp_atoms[j].
bonds.size()) {
407 void getAtomNeighborhood(std::vector<bondholder> &nbrs)
const{
408 for(
unsigned j=0; j < nbrs.size(); ++j){
409 unsigned int nbrIdx = nbrs[j].nbrIdx;
410 if(nbrIdx == ATNUM_CLASS_OFFSET){
415 nbrs[j].nbrSymClass = nbr->
getAtomicNum()*ATNUM_CLASS_OFFSET+dp_atoms[
nbrIdx].index+1;
421 int basecomp(
int i,
int j)
const {
423 unsigned int ivi,ivj;
426 ivi= dp_atoms[i].index;
427 ivj= dp_atoms[j].index;
434 ivi= dp_atoms[i].atom->getAtomicNum();
435 ivj= dp_atoms[j].atom->getAtomicNum();
442 ivi=dp_atoms[i].atom->getIsotope();
443 ivj=dp_atoms[j].atom->getIsotope();
454 ivi=cipCode==
"R"?2:1;
457 ivj=cipCode==
"R"?2:1;
483 getAtomNeighborhood(dp_atoms[i].bonds);
484 getAtomNeighborhood(dp_atoms[j].bonds);
489 for(
unsigned int ii=0;ii<dp_atoms[i].
bonds.size() && ii<dp_atoms[j].
bonds.size();++ii){
490 int cmp=
bondholder::compare(dp_atoms[i].bonds[ii],dp_atoms[j].bonds[ii],ATNUM_CLASS_OFFSET);
493 for(
unsigned int ii=0;ii<dp_atoms[i].
bonds.size() && ii<dp_atoms[j].
bonds.size();++ii){
497 if(dp_atoms[i].bonds.size()<dp_atoms[j].
bonds.size()){
499 }
else if(dp_atoms[i].bonds.size()>dp_atoms[j].
bonds.size()) {
511 template <
typename CompareFunc>
514 CompareFunc compar,
int mode,
517 int &activeset,
int *next,
519 char *touchedPartitions){
521 register int partition;
522 register int symclass;
531 while( activeset != -1 ) {
542 partition = activeset;
543 activeset = next[partition];
544 next[partition] = -2;
546 len = count[partition];
547 offset = atoms[partition].
index;
548 start = order+offset;
558 hanoisort(start,len,count,changed, compar);
564 for(
unsigned k = 0; k < len; ++k){
570 for( i=count[index]; i<len; i++ ) {
574 atoms[index].
index = symclass;
579 for(
unsigned j = 0; j < atoms[index].
degree; ++j){
580 changed[atoms[index].
nbrIds[j]]=1;
587 for( i=count[index]; i<len; i++ ) {
589 for(
unsigned j = 0; j < atoms[index].
degree; ++j){
590 unsigned int nbor = atoms[index].
nbrIds[j];
591 touchedPartitions[atoms[nbor].
index]=1;
594 for(
unsigned int ii=0; ii<nAtoms; ++ii) {
595 if(touchedPartitions[ii]){
596 partition = order[ii];
597 if( (count[partition]>1) &&
598 (next[partition]==-2) ) {
599 next[partition] = activeset;
600 activeset = partition;
602 touchedPartitions[ii] = 0;
611 template <
typename CompareFunc>
614 CompareFunc compar,
int mode,
617 int &activeset,
int *next,
619 char *touchedPartitions){
621 register int partition;
627 for(
unsigned int i=0; i<nAtoms; i++ ) {
628 partition = order[i];
629 oldPart = atoms[partition].
index;
630 while( count[partition] > 1 ) {
631 len = count[partition];
632 offset = atoms[partition].
index+len-1;
633 index = order[offset];
634 atoms[index].
index = offset;
635 count[partition] = len-1;
639 if(atoms[index].degree < 1){
642 for(
unsigned j = 0; j < atoms[index].
degree; ++j){
643 unsigned int nbor = atoms[index].
nbrIds[j];
644 touchedPartitions[atoms[nbor].
index]=1;
648 for(
unsigned int ii=0; ii<nAtoms; ++ii) {
649 if(touchedPartitions[ii]){
650 int npart = order[ii];
651 if( (count[npart]>1) &&
652 (next[npart]==-2) ) {
653 next[npart] = activeset;
656 touchedPartitions[ii] = 0;
659 RefinePartitions(mol,atoms,compar,mode,order,count,activeset,next,changed,touchedPartitions);
662 if(atoms[partition].index != oldPart){
677 int &activeset,
int *next,
682 bool includeChirality=
true,
683 bool includeIsotopes=
true);
686 const boost::dynamic_bitset<> &atomsInPlay,
687 const boost::dynamic_bitset<> &bondsInPlay,
688 const std::vector<std::string> *atomSymbols=NULL,
690 bool includeChirality=
true,
691 bool includeIsotopes=
true);
696 bool includeChirality=
true);
int operator()(int i, int j) const
const std::string * p_symbol
void chiralRankMolAtoms(const ROMol &mol, std::vector< unsigned int > &res)
SpecialSymmetryAtomCompareFunctor()
const boost::dynamic_bitset * dp_bondsInPlay
void rankMolAtoms(const ROMol &mol, std::vector< unsigned int > &res, bool breakTies=true, bool includeChirality=true, bool includeIsotopes=true)
void updateAtomNeighborIndex(canon_atom *atoms, std::vector< bondholder > &nbrs)
void CreateSinglePartition(unsigned int nAtoms, int *order, int *count, canon_atom *atoms)
void ActivatePartitions(unsigned int nAtoms, int *order, int *count, int &activeset, int *next, int *changed)
const std::string molAtomMapNumber
Defines the primary molecule class ROMol as well as associated typedefs.
void hanoisort(int *base, int nel, int *count, int *changed, CompareFunc compar)
bool df_useChiralityRings
BondStereo
the nature of the bond's stereochem (for cis/trans)
unsigned int getNumAtoms(bool onlyExplicit=1) const
returns our number of atoms
Canon::canon_atom * dp_atoms
AtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=NULL, const boost::dynamic_bitset<> *bondsInPlay=NULL)
bondholder(Bond::BondType bt, Bond::BondStereo bs, unsigned int ni, unsigned int nsc)
ROMol is a molecule class that is intended to have a fixed topology.
const boost::dynamic_bitset * dp_bondsInPlay
std::vector< bondholder > bonds
static bool greater(const bondholder &lhs, const bondholder &rhs)
ChiralAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m)
const unsigned int ATNUM_CLASS_OFFSET
Canon::canon_atom * dp_atoms
unsigned int revistedNeighbors
SpecialSymmetryAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=NULL, const boost::dynamic_bitset<> *bondsInPlay=NULL)
int getAtomicNum() const
returns our atomic number
bool operator<(const bondholder &o) const
ChiralAtomCompareFunctor()
const std::string _CIPCode
Includes a bunch of functionality for handling Atom and Bond queries.
int operator()(int i, int j) const
void BreakTies(const ROMol &mol, canon_atom *atoms, CompareFunc compar, int mode, int *order, int *count, int &activeset, int *next, int *changed, char *touchedPartitions)
Canon::canon_atom * dp_atoms
const boost::dynamic_bitset * dp_bondsInPlay
class for representing a bond
SpecialChiralityAtomCompareFunctor()
static int compare(const bondholder &x, const bondholder &y, unsigned int div=1)
void RefinePartitions(const ROMol &mol, canon_atom *atoms, CompareFunc compar, int mode, int *order, int *count, int &activeset, int *next, int *changed, char *touchedPartitions)
#define PRECONDITION(expr, mess)
void updateAtomNeighborNumSwaps(canon_atom *atoms, std::vector< bondholder > &nbrs, unsigned int atomIdx, std::vector< std::pair< unsigned int, unsigned int > > &result)
int operator()(int i, int j) const
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=NULL, bool breakTies=true, bool includeChirality=true, bool includeIsotopes=true)
int operator()(int i, int j) const
bondholder(Bond::BondType bt, unsigned int bs, unsigned int ni, unsigned int nsc)
void initCanonAtoms(const ROMol &mol, std::vector< Canon::canon_atom > &atoms, bool includeChirality=true)
SpecialChiralityAtomCompareFunctor(Canon::canon_atom *atoms, const ROMol &m, const boost::dynamic_bitset<> *atomsInPlay=NULL, const boost::dynamic_bitset<> *bondsInPlay=NULL)
The class for representing atoms.
Canon::canon_atom * dp_atoms