void AddMWMF(RWMol &mol, bool pre) { // set formula & mass properties "MW_PRE" "MW_POST" double mass = 0.0; mass = RDKit::Descriptors::calcExactMW(mol); /* for (unsigned i = 0; i < mol.getNumAtoms(); i++) { const Atom& atom = *mol.getAtomWithIdx(i); mass += atom.getMass(); mass += atom.getNumImplicitHs() * 1.0080; // and add implicit Hydrogens mass } */ std::string formula = getMolecularFormula(mol); if (!formula.empty()) mol.setProp((pre ? "MF_PRE" : "MF_POST"), formula); char propertyValue[64]; snprintf(propertyValue, sizeof(propertyValue), "%g", mass); mol.setProp((pre ? "MW_PRE" : "MW_POST"), mass); }
void test2() { #ifdef SUPPORT_COMPRESSED_IO BOOST_LOG(rdInfoLog) << "testing writing to, then reading from compressed streams" << std::endl; std::string smiles = "C1CCCC1"; std::string buff, molBlock; RWMol *m; m = SmilesToMol(smiles); TEST_ASSERT(m); TEST_ASSERT(m->getNumAtoms(5)); m->setProp(common_properties::_Name, "monkey"); io::filtering_ostream outStrm; outStrm.push(io::gzip_compressor()); outStrm.push(io::back_inserter(buff)); TEST_ASSERT(outStrm.is_complete()); molBlock = MolToMolBlock(*m); outStrm << molBlock; outStrm.reset(); delete m; io::filtering_istream inStrm; inStrm.push(io::gzip_decompressor()); inStrm.push(boost::make_iterator_range(buff)); TEST_ASSERT(inStrm.is_complete()); unsigned int lineNo = 0; m = MolDataStreamToMol(inStrm, lineNo); TEST_ASSERT(m); TEST_ASSERT(m->getNumAtoms(5)); BOOST_LOG(rdInfoLog) << "done" << std::endl; #else BOOST_LOG(rdInfoLog) << "Compressed IO disabled; test skipped" << std::endl; #endif }
int setAromaticity(RWMol &mol) { // FIX: we will assume for now that if the input molecule came // with aromaticity information it is correct and we will not // touch it. Loop through the atoms and check if any atom has // arom stuff set. We may want check this more carefully later // and start from scratch if necessary ROMol::AtomIterator ai; for (ai = mol.beginAtoms(); ai != mol.endAtoms(); ai++) { if ((*ai)->getIsAromatic()) { // found aromatic info return -1; } } // first find the all the simple rings in the molecule VECT_INT_VECT srings; if (mol.getRingInfo()->isInitialized()) { srings = mol.getRingInfo()->atomRings(); } else { MolOps::symmetrizeSSSR(mol, srings); } int narom = 0; // loop over all the atoms in the rings that can be candidates // for aromaticity // Atoms are candidates if // - it is part of ring // - has one or more electron to donate or has empty p-orbitals int natoms = mol.getNumAtoms(); boost::dynamic_bitset<> acands(natoms); boost::dynamic_bitset<> aseen(natoms); VECT_EDON_TYPE edon(natoms); VECT_INT_VECT cRings; // holder for rings that are candidates for aromaticity for (VECT_INT_VECT_I vivi = srings.begin(); vivi != srings.end(); ++vivi) { bool allAromatic = true; for (INT_VECT_I ivi = (*vivi).begin(); ivi != (*vivi).end(); ++ivi) { if (aseen[*ivi]) { if (!acands[*ivi]) allAromatic = false; continue; } aseen[*ivi] = 1; Atom *at = mol.getAtomWithIdx(*ivi); // now that the atom is part of ring check if it can donate // electron or has empty orbitals. Record the donor type // information in 'edon' - we will need it when we get to // the Huckel rule later edon[*ivi] = getAtomDonorTypeArom(at); acands[*ivi] = isAtomCandForArom(at, edon[*ivi]); if (!acands[*ivi]) allAromatic = false; } if (allAromatic) { cRings.push_back((*vivi)); } } // first convert all rings to bonds ids VECT_INT_VECT brings; RingUtils::convertToBonds(cRings, brings, mol); // make the neighbor map for the rings // i.e. a ring is a neighbor a another candidate ring if // shares at least one bond // useful to figure out fused systems INT_INT_VECT_MAP neighMap; RingUtils::makeRingNeighborMap(brings, neighMap, maxFusedAromaticRingSize); // now loop over all the candidate rings and check the // huckel rule - of course paying attention to fused systems. INT_VECT doneRs; int curr = 0; int cnrs = rdcast<int>(cRings.size()); boost::dynamic_bitset<> fusDone(cnrs); INT_VECT fused; while (curr < cnrs) { fused.resize(0); RingUtils::pickFusedRings(curr, neighMap, fused, fusDone); applyHuckelToFused(mol, cRings, brings, fused, edon, neighMap, narom, 6); int rix; for (rix = 0; rix < cnrs; rix++) { if (!fusDone[rix]) { curr = rix; break; } } if (rix == cnrs) { break; } } mol.setProp(common_properties::numArom, narom, true); return narom; }
// ------------------------------------------------------------------ // // 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; }