bool StripSmallFragments(RWMol &mol, bool verbose) { const bool sanitize=false; std::vector<boost::shared_ptr<ROMol> > frags = MolOps::getMolFrags(mol, sanitize); if (frags.size() <= 1) return false; size_t maxFragSize = 0; size_t maxFragIdx = 0; for(size_t i=0; i<frags.size(); ++i) { const unsigned int fragSize = frags[i].get()->getNumAtoms(); if(fragSize >= maxFragSize) { maxFragSize = fragSize; maxFragIdx = i; } } if(verbose) { std::string name = "<no name>"; mol.getPropIfPresent(common_properties::_Name, name); for(size_t i=0; i<frags.size(); ++i) { if (i != maxFragIdx) { BOOST_LOG(rdWarningLog) << name << " removed fragment i="<<i<<" with " << frags[i].get()->getNumAtoms() << " atoms" << std::endl; } } } // we need to save chirality for checking later bool checkChiral = false; if(mol.hasProp(RDKit::common_properties::_MolFileChiralFlag)) { unsigned int chiralflag = mol.getProp<unsigned int>( RDKit::common_properties::_MolFileChiralFlag); frags[maxFragIdx].get()->setProp<unsigned int>( RDKit::common_properties::_MolFileChiralFlag, chiralflag); checkChiral = chiralflag != 0; } mol = *frags[maxFragIdx].get(); // We need to see if the mol file's chirality possibly came from this // fragment. if (checkChiral) { bool ischiral = false; RWMol copy(mol); try { MolOps::sanitizeMol(copy); ClearSingleBondDirFlags(copy); const Conformer &conf = copy.getConformer(); DetectBondStereoChemistry(copy, &conf); MolOps::assignStereochemistry(copy, true, true, true); for (ROMol::AtomIterator atIt =copy.beginAtoms(); atIt != copy.endAtoms(); ++atIt) { if((*atIt)->hasProp(common_properties::_ChiralityPossible)) { ischiral = true; checkChiral = false; break; } } } catch (...) { } // are chiral tags set if(checkChiral) { for (ROMol::AtomIterator atIt = mol.beginAtoms(); atIt != mol.endAtoms(); ++atIt) { if ( (*atIt)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CW || (*atIt)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CCW ) { ischiral = true; break; } } for (ROMol::BondIterator bondIt = mol.beginBonds(); bondIt != mol.endBonds(); ++bondIt) { if ((*bondIt)->getBondDir() == Bond::BEGINDASH || (*bondIt)->getBondDir() == Bond::BEGINWEDGE) { ischiral = true; break; } } } if (!ischiral) { mol.setProp<unsigned int>(RDKit::common_properties::_MolFileChiralFlag, 0); } } return true; }
// ------------------------------------------------------------------ // // Enumerates the library around a template and returns the result. // // // ------------------------------------------------------------------ RWMOL_SPTR_VECT enumerateLibrary(RWMol *templateMol, VECT_RWMOL_SPTR_VECT &sidechains, bool orientSidechains){ PRECONDITION(templateMol,"bad molecule"); RWMOL_SPTR_VECT res,tmp; res.push_back(RWMOL_SPTR(new RWMol(*templateMol))); // if there's no attachment point on the molecule or no // sidechains, return now: if(!templateMol->hasProp(common_properties::maxAttachIdx) || sidechains.size()==0 ) return res; int maxIdx; templateMol->getProp(common_properties::maxAttachIdx,maxIdx); tmp.clear(); // loop over the sidechains and attach them for(unsigned int i=0;i<sidechains.size();i++){ int tgtMark=CONNECT_BOOKMARK_START+i; // here's another boundary condition if(tgtMark>maxIdx) break; /// loop over all atoms with the appropriate mark // This means that if a mol has two attachment points with the // same name (e.g. two Xa's) they'll always have the same // sidechain attached to them. This is a feature. RWMOL_SPTR_VECT::iterator sidechainIt; for(sidechainIt=sidechains[i].begin(); sidechainIt!=sidechains[i].end(); sidechainIt++){ // we've got our sidechain, find the atom it attaches from if( (*sidechainIt)->hasAtomBookmark(CONNECT_BOOKMARK_START) ){ // // NOTE: If there's more than one marked atom in the sidechain, /// we'll only use the first for the moment. // int sidechainAtomIdx = (*sidechainIt)->getAtomWithBookmark(CONNECT_BOOKMARK_START)->getIdx(); // now add the sidechain to each molecule RWMOL_SPTR_VECT::iterator templMolIt; // loop over all the mols we've generated to this point for(templMolIt=res.begin();templMolIt!=res.end();templMolIt++){ RWMol *templ = new RWMol(**templMolIt); std::string name,tmpStr; if(templ->hasProp(common_properties::_Name)){ templ->getProp(common_properties::_Name,tmpStr); name = name + " " + tmpStr; } while(templ->hasAtomBookmark(tgtMark)){ // this is the atom we'll be replacing in the template Atom *at = templ->getAtomWithBookmark(tgtMark); // copy and transform the sidechain: RWMol *sidechain; if(orientSidechains){ sidechain = new RWMol(*(sidechainIt->get())); orientSidechain(templ,sidechain, at->getIdx(),sidechainAtomIdx); } else { sidechain = sidechainIt->get(); } // FIX: need to use the actual bond order here: molAddSidechain(templ,sidechain, at->getIdx(),sidechainAtomIdx, Bond::SINGLE); if(sidechain->hasProp(common_properties::_Name)){ sidechain->getProp(common_properties::_Name,tmpStr); name = name + " " + tmpStr; } templ->clearAtomBookmark(tgtMark,at); if(orientSidechains){ delete sidechain; } } //std::cout << templ << "> " << MolToSmiles(*templ) << std::endl; if(name != "") templ->setProp(common_properties::_Name,name); tmp.push_back(RWMOL_SPTR(templ)); } } } // // if we just made any molecules, free up the memory used by the // existing result set and move the molecules we just generated // over if(tmp.size()){ #if 0 RWMOL_SPTR_VECT::iterator tmpMolIt; for(tmpMolIt=res.begin();tmpMolIt!=res.end();tmpMolIt++){ delete *tmpMolIt; } #endif res = tmp; tmp.clear(); } } return res; }