diff --git a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp index 26d075ddd..f70a505bb 100644 --- a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp +++ b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -54,7 +55,7 @@ const std::string SIDECHAIN_RLABELS = "sideChainRlabels"; bool setLabel(Atom *atom, int label, std::set &labels, int &maxLabel, bool relabel, const std::string &type) { - if(type == "IsotopeLabels") { + if (type == "IsotopeLabels") { atom->setIsotope(0); } @@ -77,9 +78,9 @@ bool setLabel(Atom *atom, int label, std::set &labels, int &maxLabel, } bool hasDummy(const RWMol &core) { - for (RWMol::ConstAtomIterator atIt = core.beginAtoms(); atIt != core.endAtoms(); - ++atIt) { - if((*atIt)->getAtomicNum() == 0) return true; + for (RWMol::ConstAtomIterator atIt = core.beginAtoms(); + atIt != core.endAtoms(); ++atIt) { + if ((*atIt)->getAtomicNum() == 0) return true; } return false; } @@ -90,30 +91,31 @@ bool RGroupDecompositionParameters::prepareCore(RWMol &core, const bool relabel = labels & RelabelDuplicateLabels; if (alignCore && (alignment & MCS)) { std::vector mols; - mols.push_back( ROMOL_SPTR(new ROMol(core)) ); - mols.push_back( ROMOL_SPTR(new ROMol(*alignCore)) ); + mols.push_back(ROMOL_SPTR(new ROMol(core))); + mols.push_back(ROMOL_SPTR(new ROMol(*alignCore))); MCSResult res = findMCS(mols); - if(res.isCompleted()) { + if (res.isCompleted()) { RWMol *m = SmartsToMol(res.SmartsString); - if(m) { + if (m) { MatchVectType match1; MatchVectType match2; - + bool target_matched1 = SubstructMatch(core, *m, match1); bool target_matched2 = SubstructMatch(*alignCore, *m, match2); CHECK_INVARIANT(match1.size() == match2.size(), "Matches should be the same size in prepareCore"); - - if(target_matched1 && target_matched2) { - for(size_t i=0;igetAtomWithIdx(alignCoreAtomIdx); + const Atom *alignCoreAtm = + alignCore->getAtomWithIdx(alignCoreAtomIdx); int rlabel = alignCoreAtm->getProp(RLABEL); coreAtm->setProp(RLABEL, rlabel); } @@ -124,40 +126,39 @@ bool RGroupDecompositionParameters::prepareCore(RWMol &core, } std::set foundLabels; - + int maxLabel = 0; int nextOffset = 0; std::map atomToLabel; - + for (RWMol::AtomIterator atIt = core.beginAtoms(); atIt != core.endAtoms(); ++atIt) { Atom *atom = *atIt; bool found = false; - - if (atom->hasProp(RLABEL)) - found = true; - + + if (atom->hasProp(RLABEL)) found = true; + if (!found && (labels & IsotopeLabels)) { if (setLabel(atom, rdcast(atom->getIsotope()), foundLabels, maxLabel, relabel, "IsotopeLabels")) - found=true; + found = true; } if (!found && (labels & AtomMapLabels)) { if (setLabel(atom, rdcast(atom->getAtomMapNum()), foundLabels, maxLabel, relabel, "AtomMapLabels")) - found=true; + found = true; } if (!found && (labels & AtomIndexLabels)) { if (setLabel(atom, indexOffset - atom->getIdx(), foundLabels, maxLabel, relabel, "IndexLabels")) nextOffset++; - found=true; + found = true; } - + int rlabel; - if(atom->getPropIfPresent(RLABEL, rlabel)) { + if (atom->getPropIfPresent(RLABEL, rlabel)) { atomToLabel[atom->getIdx()] = rlabel; } } @@ -166,11 +167,13 @@ bool RGroupDecompositionParameters::prepareCore(RWMol &core, MolOps::AdjustQueryParameters adjustParams; adjustParams.makeDummiesQueries = true; - adjustParams.adjustDegree = onlyMatchAtRGroups ? - MolOps::AdjustDegree::HeavyDegree : MolOps::AdjustDegree::NoAdjust; + adjustParams.adjustDegree = onlyMatchAtRGroups + ? MolOps::AdjustDegree::HeavyDegree + : MolOps::AdjustDegree::NoAdjust; adjustQueryProperties(core, &adjustParams); - - for(std::map::iterator it=atomToLabel.begin(); it!=atomToLabel.end(); ++it) + + for (std::map::iterator it = atomToLabel.begin(); + it != atomToLabel.end(); ++it) core.getAtomWithIdx(it->first)->setProp(RLABEL, it->second); return true; @@ -182,19 +185,19 @@ struct RGroupData { boost::shared_ptr combinedMol; std::vector > mols; // All the mols in the rgroup std::set smilesSet; // used for rgroup equivalence - std::string smiles; // smiles for all the mols in the rgroup (with attachments) - std::set attachments; // attachment points - + std::string + smiles; // smiles for all the mols in the rgroup (with attachments) + std::set attachments; // attachment points + void add(boost::shared_ptr newMol, const std::vector &rlabel_attachments) { // some fragments can be add multiple times if they are cyclic - for (size_t i=0; i getNumBondsToRlabels() const { - std::map rlabelsUsedCount; + std::map getNumBondsToRlabels() const { + std::map rlabelsUsedCount; for (ROMol::AtomIterator atIt = combinedMol->beginAtoms(); - atIt != combinedMol->endAtoms(); - ++atIt) { + atIt != combinedMol->endAtoms(); ++atIt) { Atom *atom = *atIt; - int rlabel; - if(atom->getPropIfPresent(RLABEL, rlabel)) + int rlabel; + if (atom->getPropIfPresent(RLABEL, rlabel)) rlabelsUsedCount[rlabel] += 1; } return rlabelsUsedCount; } - + bool isHydrogen() const { // is the rgroup all Hs - for(size_t i=0; ibeginAtoms(); atIt != mols[i]->endAtoms(); ++atIt) { if ((*atIt)->getAtomicNum() > 1) return false; @@ -250,10 +252,8 @@ namespace { struct RGroupMatch { size_t core_idx; std::map rgroups; - RGroupMatch( size_t core_index, const std::map &input_rgroups ) : - core_idx(core_index), rgroups(input_rgroups) { - } - + RGroupMatch(size_t core_index, const std::map &input_rgroups) + : core_idx(core_index), rgroups(input_rgroups) {} }; struct CartesianProduct { @@ -262,7 +262,9 @@ struct CartesianProduct { size_t maxPermutations; size_t permutationCount; CartesianProduct(const std::vector &inputSizes) - : permutation(inputSizes.size(), 0), sizes(inputSizes), permutationCount(0) { + : permutation(inputSizes.size(), 0), + sizes(inputSizes), + permutationCount(0) { maxPermutations = 1; for (size_t i = 0; i < sizes.size(); ++i) maxPermutations *= sizes[i]; // may overflow.... @@ -297,104 +299,107 @@ double score(const std::vector &permutation, double score = 1.; #ifdef DEBUG - std::cerr << "---------------------------------------------------" << std::endl; + std::cerr << "---------------------------------------------------" + << std::endl; std::cerr << "Scoring permutation " << std::endl; #endif - + for (std::set::const_iterator label = labels.begin(); label != labels.end(); ++label) { int l = *label; -#ifdef DEBUG +#ifdef DEBUG std::cerr << "Label: " << l << std::endl; -#endif +#endif std::map matchSet; std::map, int> linkerMatchSet; - //std::map, int > attachMatch; + // std::map, int > attachMatch; for (size_t m = 0; m < permutation.size(); ++m) { // for each molecule - std::map::const_iterator rg = matches[m][permutation[m]].rgroups.find(l); + std::map::const_iterator rg = + matches[m][permutation[m]].rgroups.find(l); if (rg != matches[m][permutation[m]].rgroups.end()) { -#ifdef DEBUG +#ifdef DEBUG std::cerr << " RGroup: " << rg->second.smiles; -#endif - matchSet[rg->second.smiles]++; -#ifdef DEBUG - std::cerr << " score: " << matchSet[rg->second.smiles] << std::endl; -#endif - // XXX Use fragment counts to see if we are linking cycles? - if(rg->second.smiles.find(".") == std::string::npos && - rg->second.attachments.size() > 1) { - linkerMatchSet[rg->second.attachments]++; -#ifdef DEBUG - std::cerr << " Linker Score: " << linkerMatchSet[rg->second.attachments]++ << std::endl; -#endif - } +#endif + matchSet[rg->second.smiles]++; +#ifdef DEBUG + std::cerr << " score: " << matchSet[rg->second.smiles] << std::endl; +#endif + // XXX Use fragment counts to see if we are linking cycles? + if (rg->second.smiles.find(".") == std::string::npos && + rg->second.attachments.size() > 1) { + linkerMatchSet[rg->second.attachments]++; +#ifdef DEBUG + std::cerr << " Linker Score: " + << linkerMatchSet[rg->second.attachments]++ << std::endl; +#endif + } } } - + // get the counts for each rgroup found and sort in reverse order std::vector equivalentRGroupCount; - + for (std::map::const_iterator it = matchSet.begin(); it != matchSet.end(); ++it) { equivalentRGroupCount.push_back(it->second); } std::sort(equivalentRGroupCount.begin(), equivalentRGroupCount.end(), std::greater()); - + double tempScore = 1.; // score the sets from the largest to the smallest // each smaller set gets penalized (i+1) below // 1.0 is the perfect score - for(size_t i=0; i, int>::const_iterator it = linkerMatchSet.begin(); + for (std::map, int>::const_iterator it = + linkerMatchSet.begin(); it != linkerMatchSet.end(); ++it) { if (it->second > 1) { - if (it->second > maxLinkerMatches) - maxLinkerMatches = it->second; + if (it->second > maxLinkerMatches) maxLinkerMatches = it->second; } } -#ifdef DEBUG +#ifdef DEBUG std::cerr << "Max Linker Matches :" << maxLinkerMatches << std::endl; #endif - double increment = 1.0; // no change in score - double linkerIncrement = 1.0; // no change in score - if(maxLinkerMatches) { + double increment = 1.0; // no change in score + double linkerIncrement = 1.0; // no change in score + if (maxLinkerMatches) { linkerIncrement = (double)(maxLinkerMatches) / (double)matches.size(); } else { increment = tempScore; } score *= increment * linkerIncrement; -#ifdef DEBUG - std::cerr << "Increment: " << increment << " Linker_Increment: " << linkerIncrement << std::endl; - std::cerr << "increment*linkerIncrement: " << increment * linkerIncrement << std::endl; +#ifdef DEBUG + std::cerr << "Increment: " << increment + << " Linker_Increment: " << linkerIncrement << std::endl; + std::cerr << "increment*linkerIncrement: " << increment * linkerIncrement + << std::endl; std::cerr << "Score = " << score << std::endl; -#endif +#endif } - + return score; } - - } -const unsigned int EMPTY_CORE_LABEL=-100000; +const unsigned int EMPTY_CORE_LABEL = -100000; struct RGroupDecompData { // matches[mol_idx] == vector of potential matches std::map cores; - std::map newCores; // new "cores" found along the way + std::map newCores; // new "cores" found along the way int newCoreLabel; RGroupDecompositionParameters params; - std::vector > matches; std::set labels; std::vector permutation; @@ -403,20 +408,25 @@ struct RGroupDecompData { std::vector processedRlabels; std::map > labelledCores; - std::map finalRlabelMapping; - + std::map finalRlabelMapping; + RGroupDecompData(const RWMol &inputCore, - const RGroupDecompositionParameters &inputParams) : - cores(), newCores(), newCoreLabel(EMPTY_CORE_LABEL), params(inputParams) { + const RGroupDecompositionParameters &inputParams) + : cores(), + newCores(), + newCoreLabel(EMPTY_CORE_LABEL), + params(inputParams) { cores[0] = inputCore; prepareCores(); } RGroupDecompData(const std::vector &inputCores, - const RGroupDecompositionParameters &inputParams) : - cores(), newCores(), newCoreLabel(EMPTY_CORE_LABEL), params(inputParams) { - - for(size_t i=0;i::iterator coreIt = cores.begin(); coreIt != cores.end(); ++coreIt, ++idx) { + for (std::map::iterator coreIt = cores.begin(); + coreIt != cores.end(); ++coreIt, ++idx) { RWMol *alignCore = coreIt->first ? &cores[0] : 0; params.prepareCore(coreIt->second, alignCore); - labelledCores[coreIt->first] = boost::shared_ptr(new RWMol(coreIt->second)); + labelledCores[coreIt->first] = + boost::shared_ptr(new RWMol(coreIt->second)); } } - + void setRlabel(Atom *atom, int rlabel) { - // XXX Fix me - use parameters to decide what to do. Currenty does everything - if (params.rgroupLabelling & AtomMap) - atom->setAtomMapNum(rlabel); - + // XXX Fix me - use parameters to decide what to do. Currenty does + // everything + if (params.rgroupLabelling & AtomMap) atom->setAtomMapNum(rlabel); + if (params.rgroupLabelling & MDLRGroup) { std::string dLabel = "R" + boost::lexical_cast(rlabel); atom->setProp(common_properties::dummyLabel, dLabel); setAtomRLabel(atom, rlabel); } - - if (params.rgroupLabelling & Isotope) - atom->setIsotope(rlabel); + + if (params.rgroupLabelling & Isotope) atom->setIsotope(rlabel); } - + void prune() { // prune all but the current "best" permutation of matches for (size_t mol_idx = 0; mol_idx < permutation.size(); ++mol_idx) { std::vector keepVector; @@ -455,36 +466,37 @@ struct RGroupDecompData { } permutation = std::vector(matches.size(), 0); } - + // Return the RGroups with the current "best" permutation // of matches. - std::vector< RGroupMatch > GetCurrentBestPermutation() const { + std::vector GetCurrentBestPermutation() const { const bool removeAllHydrogenRGroups = params.removeAllHydrogenRGroups; - - std::vector result; //std::map > result; - for(size_t i=0; i result; // std::map > result; + for (size_t i = 0; i < permutation.size(); ++i) { PRECONDITION(i < matches.size(), "Best Permutation mol idx out of range"); PRECONDITION(permutation[i] < matches[i].size(), "Selected match at permutation out of range"); - result.push_back( matches[i][permutation[i]] ); + result.push_back(matches[i][permutation[i]]); } if (removeAllHydrogenRGroups) { // if a label is all hydrogens, remove it - for(std::set::const_iterator lit = labels.begin(); - lit != labels.end(); - ++lit) { + for (std::set::const_iterator lit = labels.begin(); + lit != labels.end(); ++lit) { bool allH = true; - for(size_t i=0;i::const_iterator rgroup = result[i].rgroups.find(*lit); - if(rgroup == result[i].rgroups.end() || !rgroup->second.isHydrogen()) { + for (size_t i = 0; i < result.size(); ++i) { + std::map::const_iterator rgroup = + result[i].rgroups.find(*lit); + if (rgroup == result[i].rgroups.end() || + !rgroup->second.isHydrogen()) { allH = false; break; - } + } } - if(allH) { - for(size_t i=0;i &mappings, + void relabelCore(RWMol &mol, std::map &mappings, const std::set &userLabels, const std::set &indexLabels, std::map > extraAtomRLabels) { @@ -506,21 +517,21 @@ struct RGroupDecompData { // Some indices are attached to multiple bonds, // these rlabels should be incrementally added last int count = 0; - std::map atoms; + std::map atoms; // a core only has one labelled index // a secondary structure extraAtomRLabels contains the number // of bonds between this atom and the side chain - + // a sidechain atom has a vector of the attachments back to the // core that takes the place of numBondsToRlabel std::map > bondsToCore; - - for (RWMol::AtomIterator atIt = mol.beginAtoms(); - atIt != mol.endAtoms(); ++atIt) { + + for (RWMol::AtomIterator atIt = mol.beginAtoms(); atIt != mol.endAtoms(); + ++atIt) { Atom *atom = *atIt; - + if (atom->hasProp(RLABEL)) { int rlabel = (*atIt)->getProp(RLABEL); // user label PRECONDITION(atoms.find(rlabel) == atoms.end(), @@ -528,39 +539,35 @@ struct RGroupDecompData { atoms[rlabel] = *atIt; } } - - std::vector > atomsToAdd; // adds -R if necessary - + + std::vector > atomsToAdd; // adds -R if necessary + // Deal with user supplied labels - for(std::set::iterator it = userLabels.begin(); - it != userLabels.end(); - ++it) { - std::map::iterator atm = atoms.find(*it); - if(atm == atoms.end()) - continue; // label not used in the rgroup + for (std::set::iterator it = userLabels.begin(); + it != userLabels.end(); ++it) { + std::map::iterator atm = atoms.find(*it); + if (atm == atoms.end()) continue; // label not used in the rgroup Atom *atom = atm->second; mappings[*it] = ++count; - - if (atom->getAtomicNum() == 0) { // add to existing dummy/rlabel + + if (atom->getAtomicNum() == 0) { // add to existing dummy/rlabel setRlabel(atom, count); - } else { // adds new rlabel + } else { // adds new rlabel Atom *newAt = new Atom(0); setRlabel(newAt, count); atomsToAdd.push_back(std::make_pair(atom, newAt)); } } - + // Deal with non-user supplied labels - for(std::set::iterator it = indexLabels.begin(); - it != indexLabels.end(); - ++it) { - std::map::iterator atm = atoms.find(*it); - if(atm == atoms.end()) - continue; // label not used in the rgroup - + for (std::set::iterator it = indexLabels.begin(); + it != indexLabels.end(); ++it) { + std::map::iterator atm = atoms.find(*it); + if (atm == atoms.end()) continue; // label not used in the rgroup + Atom *atom = atm->second; mappings[*it] = ++count; - if (atom->getAtomicNum() == 0) { // add to dummy + if (atom->getAtomicNum() == 0) { // add to dummy setRlabel(atom, count); } else { Atom *newAt = new Atom(0); @@ -568,62 +575,59 @@ struct RGroupDecompData { atomsToAdd.push_back(std::make_pair(atom, newAt)); } } - + // Deal with multiple bonds to the same label - for(std::map >::iterator extraAttachments = extraAtomRLabels.begin(); - extraAttachments != extraAtomRLabels.end(); - ++extraAttachments) { - std::map::iterator atm = atoms.find(extraAttachments->first); - if(atm == atoms.end()) - continue; // label not used in the rgroup + for (std::map >::iterator extraAttachments = + extraAtomRLabels.begin(); + extraAttachments != extraAtomRLabels.end(); ++extraAttachments) { + std::map::iterator atm = atoms.find(extraAttachments->first); + if (atm == atoms.end()) continue; // label not used in the rgroup Atom *atom = atm->second; - - for(size_t i=0;isecond.size(); ++i) { + + for (size_t i = 0; i < extraAttachments->second.size(); ++i) { extraAttachments->second[i] = ++count; // Is this necessary? - PRECONDITION(atom->getAtomicNum() > 1, - "Multiple attachements to a dummy (or hydrogen) is weird."); + PRECONDITION( + atom->getAtomicNum() > 1, + "Multiple attachements to a dummy (or hydrogen) is weird."); Atom *newAt = new Atom(0); setRlabel(newAt, count); atomsToAdd.push_back(std::make_pair(atom, newAt)); } } - - for(size_t i=0; i &mappings) { + void relabelRGroup(RGroupData &rgroup, const std::map &mappings) { PRECONDITION(rgroup.combinedMol.get(), "Unprocessed rgroup"); const std::string done = "RLABEL_PROCESSED"; - if (rgroup.combinedMol->hasProp(done)) - return; - - rgroup.combinedMol->setProp(done, true); - - RWMol &mol = *rgroup.combinedMol.get(); - - std::vector > atomsToAdd; // adds -R if necessary + if (rgroup.combinedMol->hasProp(done)) return; - for (RWMol::AtomIterator atIt = mol.beginAtoms(); - atIt != mol.endAtoms(); ++atIt) { + rgroup.combinedMol->setProp(done, true); + + RWMol &mol = *rgroup.combinedMol.get(); + + std::vector > atomsToAdd; // adds -R if necessary + + for (RWMol::AtomIterator atIt = mol.beginAtoms(); atIt != mol.endAtoms(); + ++atIt) { Atom *atom = *atIt; if (atom->hasProp(SIDECHAIN_RLABELS)) { atom->setIsotope(0); - const std::vector &rlabels = atom->getProp >( - SIDECHAIN_RLABELS); + const std::vector &rlabels = + atom->getProp >(SIDECHAIN_RLABELS); // switch on atom mappings or rlabels.... - for(std::vector::const_iterator rlabel = rlabels.begin(); - rlabel != rlabels.end(); - ++rlabel) { - std::map::const_iterator label = mappings.find(*rlabel); + for (std::vector::const_iterator rlabel = rlabels.begin(); + rlabel != rlabels.end(); ++rlabel) { + std::map::const_iterator label = mappings.find(*rlabel); PRECONDITION(label != mappings.end(), "Unprocessed mapping"); - - if(atom->getAtomicNum() == 0) { + + if (atom->getAtomicNum() == 0) { setRlabel(atom, label->second); } else { Atom *newAt = new Atom(0); @@ -631,14 +635,13 @@ struct RGroupDecompData { atomsToAdd.push_back(std::make_pair(atom, newAt)); } } - } + } + } + + for (size_t i = 0; i < atomsToAdd.size(); ++i) { + mol.addAtom(atomsToAdd[i].second, false, true); + mol.addBond(atomsToAdd[i].first, atomsToAdd[i].second, Bond::SINGLE); } - - for(size_t i=0; i > extraAtomRLabels; - - for(std::vector::iterator it = best.begin(); - it != best.end(); - ++it) { - for(std::map::iterator rit = it->rgroups.begin(); - rit != it->rgroups.end(); - ++rit) { - if (rit->first >= 0) - userLabels.insert(rit->first); - if (rit->first < 0) - indexLabels.insert(rit->first); - - std::map rlabelsUsedInRGroup = rit->second.getNumBondsToRlabels(); - for(std::map::iterator numBondsUsed = rlabelsUsedInRGroup.begin(); - numBondsUsed != rlabelsUsedInRGroup.end(); - ++numBondsUsed) { + std::map > extraAtomRLabels; + + for (std::vector::iterator it = best.begin(); it != best.end(); + ++it) { + for (std::map::iterator rit = it->rgroups.begin(); + rit != it->rgroups.end(); ++rit) { + if (rit->first >= 0) userLabels.insert(rit->first); + if (rit->first < 0) indexLabels.insert(rit->first); + + std::map rlabelsUsedInRGroup = + rit->second.getNumBondsToRlabels(); + for (std::map::iterator numBondsUsed = + rlabelsUsedInRGroup.begin(); + numBondsUsed != rlabelsUsedInRGroup.end(); ++numBondsUsed) { // Make space for the extra labels - if (numBondsUsed->second > 1) { // multiple - extraAtomRLabels[numBondsUsed->first].resize( numBondsUsed->second - 1 ); + if (numBondsUsed->second > 1) { // multiple + extraAtomRLabels[numBondsUsed->first].resize(numBondsUsed->second - + 1); } } } } finalRlabelMapping.clear(); - for(std::map::const_iterator coreIt=cores.begin(); coreIt!=cores.end(); ++coreIt) { - boost::shared_ptr labelledCore( new RWMol(coreIt->second) ); + for (std::map::const_iterator coreIt = cores.begin(); + coreIt != cores.end(); ++coreIt) { + boost::shared_ptr labelledCore(new RWMol(coreIt->second)); labelledCores[coreIt->first] = labelledCore; - relabelCore(*labelledCore.get(), finalRlabelMapping, userLabels, indexLabels, - extraAtomRLabels); + relabelCore(*labelledCore.get(), finalRlabelMapping, userLabels, + indexLabels, extraAtomRLabels); } const std::string done = "RLABEL_PROCESSED"; - for(std::vector::iterator it = best.begin(); - it != best.end(); - ++it) { - for(std::map::iterator rit = it->rgroups.begin(); rit != it->rgroups.end(); ++rit) { + for (std::vector::iterator it = best.begin(); it != best.end(); + ++it) { + for (std::map::iterator rit = it->rgroups.begin(); + rit != it->rgroups.end(); ++rit) { relabelRGroup(rit->second, finalRlabelMapping); } } } - bool process(bool pruneMatches, bool finalize=false) { + bool process(bool pruneMatches, bool finalize = false) { if (matches.size() == 0) return false; - + // Exhaustive search, get the MxN matrix size_t M = matches.size(); std::vector permutations; size_t N = 1; - + for (size_t m = 0; m < M; ++m) { size_t sz = matches[m].size(); permutations.push_back(sz); @@ -716,56 +718,54 @@ struct RGroupDecompData { } permutation = std::vector(permutations.size(), 0); - + // run through all possible matches and score each // set double best_score = 0; std::vector best_permutation = permutation; size_t count = 0; -#ifdef DEBUG +#ifdef DEBUG std::cerr << "Processing" << std::endl; -#endif +#endif CartesianProduct iterator(permutations); while (iterator.next()) { if (count > N) throw ValueErrorException("Next did not finish"); -#ifdef DEBUG - std::cerr << "**************************************************" << std::endl; -#endif - double newscore = score(iterator.permutation, matches, - labels); +#ifdef DEBUG + std::cerr << "**************************************************" + << std::endl; +#endif + double newscore = score(iterator.permutation, matches, labels); if (newscore > best_score) { -#ifdef DEBUG - std::cerr << " ===> current best:" << newscore << ">" << best_score << std::endl; -#endif +#ifdef DEBUG + std::cerr << " ===> current best:" << newscore << ">" << best_score + << std::endl; +#endif best_score = newscore; best_permutation = iterator.permutation; } } - + permutation = best_permutation; if (pruneMatches || finalize) { prune(); } - - if(finalize) { + + if (finalize) { relabel(); } - + return true; } - }; RGroupDecomposition::RGroupDecomposition( const ROMol &inputCore, const RGroupDecompositionParameters ¶ms) - : data(new RGroupDecompData(inputCore, params)) { -} + : data(new RGroupDecompData(inputCore, params)) {} RGroupDecomposition::RGroupDecomposition( const std::vector &cores, const RGroupDecompositionParameters ¶ms) - : data(new RGroupDecompData(cores, params)) { -} + : data(new RGroupDecompData(cores, params)) {} RGroupDecomposition::~RGroupDecomposition() { delete data; } @@ -780,9 +780,8 @@ int RGroupDecomposition::add(const ROMol &inmol) { std::vector tmatches; // Find the first matching core. - for(std::map::const_iterator coreIt=data->cores.begin(); - coreIt != data->cores.end(); - ++coreIt) { + for (std::map::const_iterator coreIt = data->cores.begin(); + coreIt != data->cores.end(); ++coreIt) { { const bool uniquify = false; const bool recursionPossible = false; @@ -790,7 +789,7 @@ int RGroupDecomposition::add(const ROMol &inmol) { SubstructMatch(mol, coreIt->second, tmatches, uniquify, recursionPossible, useChirality); } - + if (!tmatches.size()) { continue; } else { @@ -798,8 +797,7 @@ int RGroupDecomposition::add(const ROMol &inmol) { if (data->matches.size() == 0) { // Greedy strategy just grabs the first match and // takes the best matches from the rest - if (data->params.matchingStrategy == Greedy) - tmatches.resize(1); + if (data->params.matchingStrategy == Greedy) tmatches.resize(1); } } core = &coreIt->second; @@ -808,8 +806,7 @@ int RGroupDecomposition::add(const ROMol &inmol) { } } - if(core == 0) - return -1; + if (core == 0) return -1; // strategies // ========== @@ -817,20 +814,20 @@ int RGroupDecomposition::add(const ROMol &inmol) { // May never finish due to combinitorial complexity // Greedy - matches to *FIRST* available match // GreedyChunks - default - process every N chunks - + // Should probably scan all mols first to find match with // smallest number of matches... std::vector potentialMatches; - + for (size_t match_idx = 0; match_idx < tmatches.size(); ++match_idx) { - ROMol *tMol; + boost::scoped_ptr tMol; { const bool replaceDummies = false; const bool labelByIndex = true; const bool requireDummyMatch = false; - tMol = replaceCore(mol, *core, tmatches[match_idx], replaceDummies, - labelByIndex, requireDummyMatch); + tMol.reset(replaceCore(mol, *core, tmatches[match_idx], replaceDummies, + labelByIndex, requireDummyMatch)); } if (tMol) { @@ -845,15 +842,16 @@ int RGroupDecomposition::add(const ROMol &inmol) { Atom *tmp = *atIt; unsigned int elno = tmp->getAtomicNum(); if (elno == 0) { - unsigned int index = tmp->getIsotope(); // this is the index into the core + unsigned int index = + tmp->getIsotope(); // this is the index into the core // it messes up when there are multiple ? int rlabel; - if(core->getAtomWithIdx(index)->getPropIfPresent(RLABEL, rlabel)) { + if (core->getAtomWithIdx(index)->getPropIfPresent(RLABEL, rlabel)) { std::vector rlabelsOnSideChain; tmp->getPropIfPresent(SIDECHAIN_RLABELS, rlabelsOnSideChain); rlabelsOnSideChain.push_back(rlabel); tmp->setProp(SIDECHAIN_RLABELS, rlabelsOnSideChain); - + data->labels.insert(rlabel); // keep track of all labels used attachments.push_back(rlabel); } @@ -865,38 +863,40 @@ int RGroupDecomposition::add(const ROMol &inmol) { // what to do with labelled cores ? std::string newCoreSmi = MolToSmiles(*newMol, true); - for (size_t attach_idx = 0; attach_idx < attachments.size(); ++attach_idx) { + for (size_t attach_idx = 0; attach_idx < attachments.size(); + ++attach_idx) { int rlabel = attachments[attach_idx]; match[rlabel].add(newMol, attachments); } } else { // special case, only one fragment - if(fragments.size() == 1) { // need to make a new core + if (fragments.size() == 1) { // need to make a new core // remove the sidechains RWMol newCore(mol); - - for (MatchVectType::const_iterator mvit = tmatches[match_idx].begin(); + + for (MatchVectType::const_iterator mvit = + tmatches[match_idx].begin(); mvit != tmatches[match_idx].end(); ++mvit) { const Atom *coreAtm = core->getAtomWithIdx(mvit->first); Atom *newCoreAtm = newCore.getAtomWithIdx(mvit->second); int rlabel; - if(coreAtm->getPropIfPresent(RLABEL, rlabel)) { + if (coreAtm->getPropIfPresent(RLABEL, rlabel)) { newCoreAtm->setProp(RLABEL, rlabel); } newCoreAtm->setProp("keep", true); } - - for(int aIdx=newCore.getNumAtoms()-1; aIdx>=0; --aIdx) { + + for (int aIdx = newCore.getNumAtoms() - 1; aIdx >= 0; --aIdx) { Atom *atom = newCore.getAtomWithIdx(aIdx); - if(!atom->hasProp("keep")) - newCore.removeAtom(atom); + if (!atom->hasProp("keep")) newCore.removeAtom(atom); } - if(newCore.getNumAtoms()) { + if (newCore.getNumAtoms()) { std::string newCoreSmi = MolToSmiles(newCore, true); // add a new core if possible - std::map::iterator newcore = data->newCores.find(newCoreSmi); + std::map::iterator newcore = + data->newCores.find(newCoreSmi); int core_idx = 0; - if(newcore == data->newCores.end()) { + if (newcore == data->newCores.end()) { core_idx = data->newCores[newCoreSmi] = data->newCoreLabel--; data->cores[core_idx] = newCore; return add(inmol); @@ -905,11 +905,10 @@ int RGroupDecomposition::add(const ROMol &inmol) { } } } - - if(match.size()) { + + if (match.size()) { potentialMatches.push_back(RGroupMatch(core_idx, match)); } - delete tMol; } } if (potentialMatches.size() == 0) { @@ -918,29 +917,27 @@ int RGroupDecomposition::add(const ROMol &inmol) { return -1; } - + size_t N = 1; for (size_t m = 0; m < data->matches.size(); ++m) { size_t sz = data->matches[m].size(); N *= sz; } // oops, exponential is a pain - if (N*potentialMatches.size() > 100000) { - data->permutation = - std::vector(data->matches.size(), 0); + if (N * potentialMatches.size() > 100000) { + data->permutation = std::vector(data->matches.size(), 0); data->process(true); } data->matches.push_back(potentialMatches); - data->permutation = - std::vector(data->matches.size(), 0); + data->permutation = std::vector(data->matches.size(), 0); size_t size = data->matches.size(); if (size) { if (data->params.matchingStrategy & Greedy || - (data->params.matchingStrategy & GreedyChunks && - size > 1 && size % data->params.chunkSize == 0)) + (data->params.matchingStrategy & GreedyChunks && size > 1 && + size % data->params.chunkSize == 0)) data->process(true); } return data->matches.size() - 1; @@ -951,71 +948,68 @@ bool RGroupDecomposition::process() { const bool prune = true; const bool finalize = true; return data->process(prune, finalize); - } catch(...) { + } catch (...) { return false; } } -RGroupRows RGroupDecomposition::getRGroupsAsRows() - const { +RGroupRows RGroupDecomposition::getRGroupsAsRows() const { std::vector permutation = data->GetCurrentBestPermutation(); - + RGroupRows groups; - int molidx=0; + int molidx = 0; for (std::vector::iterator it = permutation.begin(); - it != permutation.end(); - ++it, ++molidx) { + it != permutation.end(); ++it, ++molidx) { // make a new rgroup entry groups.push_back(RGroupRow()); RGroupRow &out_rgroups = groups.back(); out_rgroups["Core"] = data->labelledCores[it->core_idx]; - + std::map &in_rgroups = it->rgroups; - + for (std::map::const_iterator rgroup = in_rgroups.begin(); rgroup != in_rgroups.end(); ++rgroup) { - std::map::const_iterator realLabel = data->finalRlabelMapping.find(rgroup->first); + std::map::const_iterator realLabel = + data->finalRlabelMapping.find(rgroup->first); PRECONDITION(realLabel != data->finalRlabelMapping.end(), "unprocessed rlabel, please call process() first."); - out_rgroups[std::string("R") + boost::lexical_cast(realLabel->second)] = \ + out_rgroups[std::string("R") + + boost::lexical_cast(realLabel->second)] = rgroup->second.combinedMol; } } return groups; } //! return rgroups in column order group[attachment_point][molidx] = ROMol -RGroupColumns RGroupDecomposition::getRGroupsAsColumns() - const { +RGroupColumns RGroupDecomposition::getRGroupsAsColumns() const { std::vector permutation = data->GetCurrentBestPermutation(); - + RGroupColumns groups; - int molidx=0; + unsigned int molidx = 0; for (std::vector::iterator it = permutation.begin(); - it != permutation.end(); - ++it, ++molidx) { + it != permutation.end(); ++it, ++molidx) { std::map &in_rgroups = it->rgroups; groups["Core"].push_back(data->labelledCores[it->core_idx]); - + for (std::map::const_iterator rgroup = in_rgroups.begin(); rgroup != in_rgroups.end(); ++rgroup) { - std::map::const_iterator realLabel = data->finalRlabelMapping.find(rgroup->first); + std::map::const_iterator realLabel = + data->finalRlabelMapping.find(rgroup->first); PRECONDITION(realLabel != data->finalRlabelMapping.end(), "unprocessed rlabel, please call process() first."); - std::string r = std::string("R") + boost::lexical_cast(realLabel->second); + std::string r = std::string("R") + + boost::lexical_cast(realLabel->second); RGroupColumn &col = groups[r]; - if(molidx && col.size() < (size_t)(molidx - 1)) - col.resize( molidx - 1 ); - col.push_back( rgroup->second.combinedMol ); + if (molidx && col.size() < (size_t)(molidx - 1)) col.resize(molidx - 1); + col.push_back(rgroup->second.combinedMol); } } // Now make all columns equal - for(std::map::iterator it = groups.begin(); - it != groups.end(); - ++it) { - if (it->second.size() != molidx) - it->second.resize(molidx); + for (std::map::iterator it = groups.begin(); + it != groups.end(); ++it) { + if (it->second.size() != molidx) it->second.resize(molidx); } return groups; } diff --git a/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp b/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp index 1a566e101..0bb99060c 100644 --- a/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp +++ b/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp @@ -42,47 +42,44 @@ using namespace RDKit; -void CHECK_RGROUP( RGroupRows::const_iterator &it, - std::string expected, bool doassert=true ) { +void CHECK_RGROUP(RGroupRows::const_iterator &it, std::string expected, + bool doassert = true) { std::ostringstream str; - int i=0; + int i = 0; - for(std::map >::const_iterator rgroups = it->begin(); - rgroups != it->end(); - ++rgroups,++i) { - if(i) str << " "; + for (std::map >::const_iterator + rgroups = it->begin(); + rgroups != it->end(); ++rgroups, ++i) { + if (i) str << " "; // rlabel:smiles str << rgroups->first << ":" << MolToSmiles(*rgroups->second.get(), true); } std::string result = str.str(); - - if(expected != result) { + + if (expected != result) { std::cerr << "Expected: " << expected << std::endl; std::cerr << "Got: " << result << std::endl; } - - if(doassert) - TEST_ASSERT(result == expected); + + if (doassert) TEST_ASSERT(result == expected); } -void DUMP_RGROUP( RGroupRows::const_iterator &it, - std::string result) { +void DUMP_RGROUP(RGroupRows::const_iterator &it, std::string &result) { std::ostringstream str; - for(std::map >::const_iterator rgroups = it->begin(); - rgroups != it->end(); - ++rgroups) { + for (std::map >::const_iterator + rgroups = it->begin(); + rgroups != it->end(); ++rgroups) { // rlabel:smiles - str << rgroups->first << "\t" << MolToSmiles(*rgroups->second.get(), true) << "\t"; + str << rgroups->first << "\t" << MolToSmiles(*rgroups->second.get(), true) + << "\t"; } std::cerr << str.str() << std::endl; + result = str.str(); } -const char *symdata[5] = {"c1(Cl)ccccc1", - "c1c(Cl)cccc1", - "c1c(Cl)cccc1", - "c1cc(Cl)ccc1", - "c1ccc(Cl)cc1"}; +const char *symdata[5] = {"c1(Cl)ccccc1", "c1c(Cl)cccc1", "c1c(Cl)cccc1", + "c1cc(Cl)ccc1", "c1ccc(Cl)cc1"}; void testSymmetryMatching() { BOOST_LOG(rdInfoLog) @@ -91,7 +88,7 @@ void testSymmetryMatching() { RWMol *core = SmilesToMol("c1ccccc1"); RGroupDecomposition decomp(*core); - for(int i=0; i<5; ++i) { + for (int i = 0; i < 5; ++i) { ROMol *mol = SmilesToMol(symdata[i]); int res = decomp.add(*mol); TEST_ASSERT(res == i); @@ -105,35 +102,34 @@ void testSymmetryMatching() { std::ostringstream str; // All Cl's should be labeled with the same rgroup - for(RGroupRows::const_iterator it = rows.begin(); it!=rows.end(); ++it) { - CHECK_RGROUP( it, "Core:c1ccc([*:1])cc1 R1:Cl[*:1]" ); + for (RGroupRows::const_iterator it = rows.begin(); it != rows.end(); ++it) { + CHECK_RGROUP(it, "Core:c1ccc([*:1])cc1 R1:Cl[*:1]"); } + delete core; } -const char *matchRGroupOnlyData[5] = {"c1(Cl)ccccc1", - "c1c(Cl)cccc1", - "c1cc(Cl)ccc1", - "c1ccc(Cl)cc1", - "c1c(Cl)cccc(I)1", +const char *matchRGroupOnlyData[5] = { + "c1(Cl)ccccc1", "c1c(Cl)cccc1", "c1cc(Cl)ccc1", + "c1ccc(Cl)cc1", "c1c(Cl)cccc(I)1", }; void testRGroupOnlyMatching() { BOOST_LOG(rdInfoLog) << "********************************************************\n"; - BOOST_LOG(rdInfoLog) << "test rgroup decomp rgroup only matching" << std::endl; + BOOST_LOG(rdInfoLog) << "test rgroup decomp rgroup only matching" + << std::endl; RWMol *core = SmilesToMol("c1ccccc1[1*]"); RGroupDecompositionParameters params(IsotopeLabels); params.onlyMatchAtRGroups = true; RGroupDecomposition decomp(*core, params); - for(int i=0; i<5; ++i) { + for (int i = 0; i < 5; ++i) { ROMol *mol = SmilesToMol(matchRGroupOnlyData[i]); int res = decomp.add(*mol); if (i < 4) { TEST_ASSERT(res == i); - } - else { + } else { TEST_ASSERT(res == -1); } delete mol; @@ -145,22 +141,19 @@ void testRGroupOnlyMatching() { std::ostringstream str; // All Cl's should be labeled with the same rgroup - int i=0; - for(RGroupRows::const_iterator it = rows.begin(); it!=rows.end(); ++it, ++i) { - CHECK_RGROUP( it, "Core:c1ccc([*:1])cc1 R1:Cl[*:1]" ); + int i = 0; + for (RGroupRows::const_iterator it = rows.begin(); it != rows.end(); + ++it, ++i) { + CHECK_RGROUP(it, "Core:c1ccc([*:1])cc1 R1:Cl[*:1]"); } + delete core; } -const char *ringData[3] = {"c1cocc1", - "c1c[nH]cc1", - "c1cscc1" -}; +const char *ringData[3] = {"c1cocc1", "c1c[nH]cc1", "c1cscc1"}; const char *ringDataRes[3] = {"Core:c1cc:[*:1]:c1 R1:o(:[*:1]):[*:1]", "Core:c1cc:[*:1]:c1 R1:[H]n(:[*:1]):[*:1]", - "Core:c1cc:[*:1]:c1 R1:s(:[*:1]):[*:1]" -}; - + "Core:c1cc:[*:1]:c1 R1:s(:[*:1]):[*:1]"}; void testRingMatching() { BOOST_LOG(rdInfoLog) @@ -169,12 +162,13 @@ void testRingMatching() { RWMol *core = SmilesToMol("c1ccc[1*]1"); RGroupDecompositionParameters params(IsotopeLabels); - + RGroupDecomposition decomp(*core, params); - for(int i=0; i<3; ++i) { + for (int i = 0; i < 3; ++i) { ROMol *mol = SmilesToMol(ringData[i]); int res = decomp.add(*mol); TEST_ASSERT(res == i); + delete mol; } decomp.process(); @@ -183,39 +177,37 @@ void testRingMatching() { std::ostringstream str; // All Cl's should be labeled with the same rgroup - int i=0; - for(RGroupRows::const_iterator it = rows.begin(); it!=rows.end(); ++it, ++i) { - CHECK_RGROUP( it, ringDataRes[i]); + int i = 0; + for (RGroupRows::const_iterator it = rows.begin(); it != rows.end(); + ++it, ++i) { + CHECK_RGROUP(it, ringDataRes[i]); } - + delete core; } - -const char *ringData2[3] = {"c1cocc1CCl", - "c1c[nH]cc1CI", - "c1cscc1CF" -}; +const char *ringData2[3] = {"c1cocc1CCl", "c1c[nH]cc1CI", "c1cscc1CF"}; const char *ringDataRes2[3] = { - "Core:[*]1[*][*][*:1](C[*:2])[*]1 R1:[H]c1oc([H])c([*:1])c1[H] R2:Cl[*:2]", - "Core:[*]1[*][*][*:1](C[*:2])[*]1 R1:[H]c1c([*:1])c([H])n([H])c1[H] R2:I[*:2]", - "Core:[*]1[*][*][*:1](C[*:2])[*]1 R1:[H]c1sc([H])c([*:1])c1[H] R2:F[*:2]" -}; - + "Core:[*]1[*][*][*:1](C[*:2])[*]1 R1:[H]c1oc([H])c([*:1])c1[H] R2:Cl[*:2]", + "Core:[*]1[*][*][*:1](C[*:2])[*]1 R1:[H]c1c([*:1])c([H])n([H])c1[H] " + "R2:I[*:2]", + "Core:[*]1[*][*][*:1](C[*:2])[*]1 R1:[H]c1sc([H])c([*:1])c1[H] R2:F[*:2]"}; void testRingMatching2() { BOOST_LOG(rdInfoLog) << "********************************************************\n"; - BOOST_LOG(rdInfoLog) << "test rgroup decomp full ring dummy core" << std::endl; - + BOOST_LOG(rdInfoLog) << "test rgroup decomp full ring dummy core" + << std::endl; + RWMol *core = SmartsToMol("*1***[*:1]1C[*:2]"); RGroupDecompositionParameters params; - + RGroupDecomposition decomp(*core, params); - for(int i=0; i<3; ++i) { + for (int i = 0; i < 3; ++i) { ROMol *mol = SmilesToMol(ringData2[i]); int res = decomp.add(*mol); TEST_ASSERT(res == i); + delete mol; } decomp.process(); @@ -223,34 +215,32 @@ void testRingMatching2() { std::ostringstream str; // All Cl's should be labeled with the same rgroup - int i=0; - for(RGroupRows::const_iterator it = rows.begin(); it!=rows.end(); ++it, ++i) { - CHECK_RGROUP( it, ringDataRes2[i]); + int i = 0; + for (RGroupRows::const_iterator it = rows.begin(); it != rows.end(); + ++it, ++i) { + CHECK_RGROUP(it, ringDataRes2[i]); } - + delete core; } -const char *ringData3[3] = {"c1cocc1CCl", - "c1c[nH]cc1CI", - "c1cscc1CF" -}; +const char *ringData3[3] = {"c1cocc1CCl", "c1c[nH]cc1CI", "c1cscc1CF"}; const char *ringDataRes3[3] = { - "Core:c1co([*:2])cc1[*:1] R1:[H]C([H])(Cl)[*:1]", - "Core:c1cn([*:2])cc1[*:1] R1:[H]C([H])(I)[*:1] R2:[H][*:2]", - "Core:c1cs([*:2])cc1[*:1] R1:[H]C([H])(F)[*:1]" -}; + "Core:c1co([*:2])cc1[*:1] R1:[H]C([H])(Cl)[*:1]", + "Core:c1cn([*:2])cc1[*:1] R1:[H]C([H])(I)[*:1] R2:[H][*:2]", + "Core:c1cs([*:2])cc1[*:1] R1:[H]C([H])(F)[*:1]"}; void testRingMatching3() { BOOST_LOG(rdInfoLog) << "********************************************************\n"; - BOOST_LOG(rdInfoLog) << "test rgroup decomp full ring dummy core" << std::endl; - + BOOST_LOG(rdInfoLog) << "test rgroup decomp full ring dummy core" + << std::endl; + RWMol *core = SmartsToMol("*1***[*:1]1"); RGroupDecompositionParameters params; - + RGroupDecomposition decomp(*core, params); - for(int i=0; i<3; ++i) { + for (int i = 0; i < 3; ++i) { ROMol *mol = SmilesToMol(ringData3[i]); int res = decomp.add(*mol); delete mol; @@ -263,58 +253,48 @@ void testRingMatching3() { std::ostringstream str; // All Cl's should be labeled with the same rgroup - int i=0; - for(RGroupRows::const_iterator it = rows.begin(); it!=rows.end(); ++it, ++i) { - CHECK_RGROUP( it, ringDataRes3[i]); + int i = 0; + for (RGroupRows::const_iterator it = rows.begin(); it != rows.end(); + ++it, ++i) { + CHECK_RGROUP(it, ringDataRes3[i]); } - + delete core; } const char *coreSmi[] = { - "C1CCNC(Cl)CC1", - "C1CC(Cl)NCCC1", - "C1CCNC(I)CC1", - "C1CC(I)NCCC1", - - "C1CCSC(Cl)CC1", - "C1CC(Cl)SCCC1", - "C1CCSC(I)CC1", - "C1CC(I)SCCC1", - - "C1CCOC(Cl)CC1", - "C1CC(Cl)OCCC1", - "C1CCOC(I)CC1", - "C1CC(I)OCCC1" -}; + "C1CCNC(Cl)CC1", "C1CC(Cl)NCCC1", "C1CCNC(I)CC1", "C1CC(I)NCCC1", + + "C1CCSC(Cl)CC1", "C1CC(Cl)SCCC1", "C1CCSC(I)CC1", "C1CC(I)SCCC1", + + "C1CCOC(Cl)CC1", "C1CC(Cl)OCCC1", "C1CCOC(I)CC1", "C1CC(I)OCCC1"}; const char *coreSmiRes[] = { - "Core:C1CCC([*:1])N([*:2])CC1 R1:Cl[*:1].[H][*:1] R2:[H][*:2]", - "Core:C1CCC([*:1])N([*:2])CC1 R1:Cl[*:1].[H][*:1] R2:[H][*:2]", - "Core:C1CCC([*:1])N([*:2])CC1 R1:I[*:1].[H][*:1] R2:[H][*:2]", - "Core:C1CCC([*:1])N([*:2])CC1 R1:I[*:1].[H][*:1] R2:[H][*:2]", - "Core:C1CCSC([*:1])CC1 R1:Cl[*:1].[H][*:1]", - "Core:C1CCSC([*:1])CC1 R1:Cl[*:1].[H][*:1]", - "Core:C1CCSC([*:1])CC1 R1:I[*:1].[H][*:1]", - "Core:C1CCSC([*:1])CC1 R1:I[*:1].[H][*:1]", - "Core:C1CCOC([*:1])CC1 R1:Cl[*:1].[H][*:1]", - "Core:C1CCOC([*:1])CC1 R1:Cl[*:1].[H][*:1]", - "Core:C1CCOC([*:1])CC1 R1:I[*:1].[H][*:1]", - "Core:C1CCOC([*:1])CC1 R1:I[*:1].[H][*:1]" -}; + "Core:C1CCC([*:1])N([*:2])CC1 R1:Cl[*:1].[H][*:1] R2:[H][*:2]", + "Core:C1CCC([*:1])N([*:2])CC1 R1:Cl[*:1].[H][*:1] R2:[H][*:2]", + "Core:C1CCC([*:1])N([*:2])CC1 R1:I[*:1].[H][*:1] R2:[H][*:2]", + "Core:C1CCC([*:1])N([*:2])CC1 R1:I[*:1].[H][*:1] R2:[H][*:2]", + "Core:C1CCSC([*:1])CC1 R1:Cl[*:1].[H][*:1]", + "Core:C1CCSC([*:1])CC1 R1:Cl[*:1].[H][*:1]", + "Core:C1CCSC([*:1])CC1 R1:I[*:1].[H][*:1]", + "Core:C1CCSC([*:1])CC1 R1:I[*:1].[H][*:1]", + "Core:C1CCOC([*:1])CC1 R1:Cl[*:1].[H][*:1]", + "Core:C1CCOC([*:1])CC1 R1:Cl[*:1].[H][*:1]", + "Core:C1CCOC([*:1])CC1 R1:I[*:1].[H][*:1]", + "Core:C1CCOC([*:1])CC1 R1:I[*:1].[H][*:1]"}; void testMultiCore() { BOOST_LOG(rdInfoLog) << "********************************************************\n"; BOOST_LOG(rdInfoLog) << "test multi core" << std::endl; std::vector cores; - cores.push_back( ROMOL_SPTR(SmartsToMol("C1CCNCCC1")) ); - cores.push_back( ROMOL_SPTR(SmilesToMol("C1CCOCCC1")) ); - cores.push_back( ROMOL_SPTR(SmilesToMol("C1CCSCCC1")) ); + cores.push_back(ROMOL_SPTR(SmartsToMol("C1CCNCCC1"))); + cores.push_back(ROMOL_SPTR(SmilesToMol("C1CCOCCC1"))); + cores.push_back(ROMOL_SPTR(SmilesToMol("C1CCSCCC1"))); RGroupDecomposition decomp(cores); - for(int i=0; i