diff --git a/Code/GraphMol/RGroupDecomposition/RGroupCore.cpp b/Code/GraphMol/RGroupDecomposition/RGroupCore.cpp index a77c64fec..b49eb9b65 100644 --- a/Code/GraphMol/RGroupDecomposition/RGroupCore.cpp +++ b/Code/GraphMol/RGroupDecomposition/RGroupCore.cpp @@ -418,6 +418,23 @@ void RCore::buildMatchingMol() { // then keep one attachment if (atom->getAtomicNum() == 0 && atom->getDegree() == 1 && isDummyRGroupAttachment(*atom)) { + // if we are a query in disguise, don't strip + if (atom->hasQuery()) { + auto q = atom->getQuery()->getDescription(); + // If we are anything but AtomNull or AtomAtomicNum we are not + // fully a dummy atom + if (q != "AtomNull" && q != "AtomAtomicNum") { + unsigned int type = 0xFFFFFFFF; + // If we are were set as an RLABEL of type Isotope we probably + // have a query of named "AtomIsotope" + // we DO strip these unless they have an additional query + if (q != "AtomIsotope" || !atom->getPropIfPresent(RLABEL_TYPE, type) || + type != RGroupLabels::IsotopeLabels) { + continue; + } + } + } + // remove terminal user R groups and map the index of the core neighbor // atom to the index of the removed terminal R group const int neighborIdx = *matchingMol->getAtomNeighbors(atom).first; diff --git a/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp b/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp index 2dab6cb39..4b954aa19 100644 --- a/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp +++ b/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp @@ -4146,13 +4146,42 @@ void testRgroupDecompZipping() { } } +void testSmartsOnDummyAtoms() { + BOOST_LOG(rdInfoLog) + << "********************************************************\n"; + BOOST_LOG(rdInfoLog) + << "Test we can reconstruct rgroup decomps that break rings" << std::endl; + + const auto core = "[$([1C]):1]C[$([2C]):2]"_smarts; + + const auto mol1 = "N[1C]C[2C]"_smiles; + const auto mol2 = "N[2C]C[1C]"_smiles; + + const std::vector expected = { + "Core:C([*:1])[*:2] R1:N[1C][*:1] R2:[2C][*:2]", + "Core:C([*:1])[*:2] R1:[1C][*:1] R2:N[2C][*:2]" + }; + + RGroupDecomposition decomp(*core); + auto add11 = decomp.add(*mol1); + TEST_ASSERT(add11 == 0); + add11 = decomp.add(*mol2); + TEST_ASSERT(add11 == 1) + decomp.process(); + RGroupRows rows = decomp.getRGroupsAsRows(); + int i = 0; + for (RGroupRows::const_iterator it = rows.begin(); it != rows.end(); + ++it, ++i) { + CHECK_RGROUP(it, expected[i]); + } +} + int main() { RDLog::InitLogs(); boost::logging::disable_logs("rdApp.debug"); BOOST_LOG(rdInfoLog) << "********************************************************\n"; BOOST_LOG(rdInfoLog) << "Testing R-Group Decomposition \n"; - testSymmetryMatching(FingerprintVariance); testSymmetryMatching(); testRGroupOnlyMatching(); @@ -4210,6 +4239,7 @@ int main() { testStereoBondBug(); testNotEnumeratedCore(); testRgroupDecompZipping(); + testSmartsOnDummyAtoms(); BOOST_LOG(rdInfoLog) << "********************************************************\n"; return 0;