// $Id$ // // Copyright (C) 2006-2015 Greg Landrum // // @@ All Rights Reserved @@ // This file is part of the RDKit. // The contents are covered by the terms of the BSD license // which is included in the file license.txt, found at the root // of the RDKit source tree. // #include #include #include #include #include #include #include #include #include #include #include #include using namespace RDKit; void testDeleteSubstruct() { ROMol *mol1 = 0, *mol2 = 0, *matcher1 = 0, *matcher2 = 0, *matcher3 = 0; std::string smi, sma; BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing deleteSubstruct" << std::endl; // a lot of the seemingly repetitive stuff is here for Issue96 smi = "CCC(=O).C=O"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); TEST_ASSERT(mol1->getNumAtoms() == 6) sma = "C=O"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); mol2 = deleteSubstructs(*mol1, *matcher1, 0); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 2) mol2 = deleteSubstructs(*mol2, *matcher1, 0); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 2) delete matcher1; sma = "[Cl;H1&X1,-]"; matcher1 = SmartsToMol(sma); sma = "[Na+]"; matcher2 = SmartsToMol(sma); sma = "[O;H2,H1&-,X0&-2]"; matcher3 = SmartsToMol(sma); delete mol1; mol1 = SmilesToMol("CCO.Cl"); TEST_ASSERT(mol1); TEST_ASSERT(mol1->getNumAtoms() == 4); delete mol2; mol2 = deleteSubstructs(*mol1, *matcher1, true); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 3); mol2 = deleteSubstructs(*mol2, *matcher2, true); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 3); mol2 = deleteSubstructs(*mol2, *matcher3, true); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 3); delete mol1; mol1 = SmilesToMol("CC(=O)[O-].[Na+]"); TEST_ASSERT(mol1); TEST_ASSERT(mol1->getNumAtoms() == 5); delete matcher1; matcher1 = SmartsToMol("[Cl;H1&X1,-]"); delete matcher2; matcher2 = SmartsToMol("[Na+]"); mol2 = deleteSubstructs(*mol1, *matcher1, true); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 5); mol2 = deleteSubstructs(*mol2, *matcher2, true); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 4); mol2 = deleteSubstructs(*mol2, *matcher1, true); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 4); BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testReplaceSubstructs() { ROMol *mol1 = 0, *matcher1 = 0, *frag = 0; std::string smi, sma; std::vector vect; BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing replaceSubstruct" << std::endl; smi = "CCCC"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); sma = "C(=O)O"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); smi = "N"; frag = SmilesToMol(smi); TEST_ASSERT(frag); vect = replaceSubstructs(*mol1, *matcher1, *frag); TEST_ASSERT(vect.size() == 1); TEST_ASSERT(mol1->getNumAtoms() == 4); TEST_ASSERT(vect[0]->getNumAtoms() == 4); delete mol1; smi = "CCCC(=O)O"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); vect = replaceSubstructs(*mol1, *matcher1, *frag); TEST_ASSERT(vect.size() == 1); TEST_ASSERT(mol1->getNumAtoms() == 6); TEST_ASSERT(vect[0]->getNumAtoms() == 4); vect = replaceSubstructs(*mol1, *matcher1, *frag, true); TEST_ASSERT(vect.size() == 1); TEST_ASSERT(mol1->getNumAtoms() == 6); TEST_ASSERT(vect[0]->getNumAtoms() == 4); delete mol1; smi = "OC(=O)CCCC(=O)O"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); vect = replaceSubstructs(*mol1, *matcher1, *frag); TEST_ASSERT(vect.size() == 2); TEST_ASSERT(mol1->getNumAtoms() == 9); TEST_ASSERT(vect[0]->getNumAtoms() == 7); TEST_ASSERT(vect[1]->getNumAtoms() == 7); // use replaceAll when a single replacement is available: vect = replaceSubstructs(*mol1, *matcher1, *frag, true); TEST_ASSERT(vect.size() == 1); TEST_ASSERT(mol1->getNumAtoms() == 9); TEST_ASSERT(vect[0]->getNumAtoms() == 5); delete matcher1; sma = "C=O"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); delete mol1; smi = "CC(=O)C"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); vect = replaceSubstructs(*mol1, *matcher1, *frag); TEST_ASSERT(vect.size() == 1); TEST_ASSERT(mol1->getNumAtoms() == 4); TEST_ASSERT(vect[0]->getNumAtoms() == 3); delete mol1; smi = "C1C(=O)C1"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); vect = replaceSubstructs(*mol1, *matcher1, *frag); TEST_ASSERT(vect.size() == 1); TEST_ASSERT(mol1->getNumAtoms() == 4); TEST_ASSERT(vect[0]->getNumAtoms() == 3); TEST_ASSERT(vect[0]->getNumBonds() == 3); BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testReplaceSubstructs2() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "More testing of replaceSubstruct" << std::endl; { std::string smi = "CCC(=O)O"; ROMol *mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); std::string sma = "[$(O-C(=O))]"; ROMol *matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); std::string repl = "NC"; ROMol *frag = SmilesToMol(repl); TEST_ASSERT(frag); std::vector vect = replaceSubstructs(*mol1, *matcher1, *frag); TEST_ASSERT(vect.size() == 1); TEST_ASSERT(mol1->getNumAtoms() == 5); TEST_ASSERT(vect[0]->getNumAtoms() == 6); std::string csmi1 = MolToSmiles(*vect[0], true); repl = "CN"; delete frag; frag = SmilesToMol(repl); TEST_ASSERT(frag); vect = replaceSubstructs(*mol1, *matcher1, *frag, true, 1); TEST_ASSERT(vect.size() == 1); TEST_ASSERT(mol1->getNumAtoms() == 5); TEST_ASSERT(vect[0]->getNumAtoms() == 6); std::string csmi2 = MolToSmiles(*vect[0], true); TEST_ASSERT(csmi2 == csmi1); delete mol1; delete matcher1; } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testReplaceSidechains() { ROMol *mol1 = 0, *mol2 = 0, *matcher1 = 0; std::string smi, sma; BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing replaceSidechains" << std::endl; smi = "ClC1CC(F)C1"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); sma = "C1CCC1"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); mol2 = replaceSidechains(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 6); delete mol1; smi = "ClC1C(F)C1"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); mol2 = replaceSidechains(*mol1, *matcher1); TEST_ASSERT(!mol2); delete matcher1; sma = "C=O"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); delete mol1; smi = "CC=O"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete mol2; mol2 = replaceSidechains(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 3); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*]C=O"); delete mol1; smi = "CC(C)=O"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete mol2; mol2 = replaceSidechains(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 4); smi = MolToSmiles(*mol2, true); // there's no way to guarantee the order here: TEST_ASSERT(smi == "[1*]C([2*])=O" || smi == "[2*]C([1*])=O"); delete mol1; delete mol2; delete matcher1; BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testReplaceCore() { ROMol *mol1 = 0, *mol2 = 0, *matcher1 = 0; std::string smi, sma; BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing replaceCore" << std::endl; smi = "ClC1CC(F)C1"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); sma = "C1CC1"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(!mol2); smi = "ClC1CC(F)C1"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); sma = "C1CCC1"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 4); smi = MolToSmiles(*mol2, true); // there's no way to guarantee the order here: TEST_ASSERT(smi == "[1*]Cl.[2*]F" || smi == "[2*]Cl.[1*]F"); delete mol1; smi = "CCC=O"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete matcher1; sma = "C=O"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 3); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*]CC"); delete mol1; smi = "C1C(=O)CC1"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete matcher1; sma = "C=O"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 5); smi = MolToSmiles(*mol2, true); // there's no way to guarantee the order here: TEST_ASSERT(smi == "[1*]CCC[2*]" || smi == "[1*]CCC[2*]"); delete mol1; smi = "CNC"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete matcher1; sma = "N"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 4); smi = MolToSmiles(*mol2, true); // there's no way to guarantee the order here: TEST_ASSERT(smi == "[1*]C.[2*]C" || smi == "[2*]C.[1*]C"); delete mol1; smi = "OC1CCC1"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete matcher1; sma = "[CH2][CH2][CH2]"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); smi = MolToSmiles(*mol2, true); TEST_ASSERT(mol2->getNumAtoms() == 4); smi = MolToSmiles(*mol2, true); // there's no way to guarantee the order here: TEST_ASSERT(smi == "[2*]C([1*])O" || smi == "[1*]C([2*])O"); delete mol1; smi = "C/C=C/CN/C=C/O"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete matcher1; sma = "N"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 9); smi = MolToSmiles(*mol2, true); // there's no way to guarantee the order here: TEST_ASSERT(smi == "[1*]C/C=C/C.[2*]/C=C/O" || smi == "[1*]/C=C/O.[2*]C/C=C/C"); delete mol1; smi = "C[C@](F)(Cl)N"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete matcher1; sma = "N"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 5); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*][C@@](C)(F)Cl"); delete mol1; smi = "C[C@](F)(N)Cl"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 5); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*][C@](C)(F)Cl"); delete mol1; smi = "N[C@](C)(F)Cl"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 5); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*][C@](C)(F)Cl"); delete mol1; smi = "C[C@@](F)(Cl)N"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete matcher1; sma = "N"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 5); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*][C@](C)(F)Cl"); delete mol1; smi = "C[C@@](F)(N)Cl"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 5); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*][C@@](C)(F)Cl"); smi = "C[C@@](N)(Cl)F"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 5); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*][C@@](C)(F)Cl"); delete mol1; smi = "C[C@H](F)N"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete matcher1; sma = "N"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 4); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*][C@H](C)F"); delete mol1; smi = "C[C@H](N)F"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 4); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*][C@@H](C)F"); delete mol1; smi = "N[C@H](C)F"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 4); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*][C@H](C)F"); delete mol1; smi = "F[C@H](C)N"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 4); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*][C@@H](C)F"); delete mol1; smi = "N[C@H]1CCCO1"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete mol2; mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 6); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*][C@H]1CCCO1"); delete mol1; smi = "ClC1CC(F)C1"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); delete matcher1; sma = "[*]C1CC([*])C1"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); mol2 = replaceCore(*mol1, *matcher1, false); TEST_ASSERT(mol2); smi = MolToSmiles(*mol2, true); TEST_ASSERT(mol2->getNumAtoms() == 4); smi = MolToSmiles(*mol2, true); // there's no way to guarantee the order here: TEST_ASSERT(smi == "[1*]F.[2*]Cl" || smi == "[1*]Cl.[2*]F"); delete mol1; delete mol2; delete matcher1; BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testReplaceCoreLabels() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing replaceCore with labels" << std::endl; { std::string sma = "n1cocc1"; ROMol *matcher = SmartsToMol(sma); TEST_ASSERT(matcher); std::string smi = "n1c(CC)oc(C)c1"; ROMol *mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); ROMol *mol2 = replaceCore(*mol1, *matcher, true, true); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 5); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*]CC.[3*]C"); delete mol1; delete mol2; delete matcher; } { std::string sma = "n1cocc1"; ROMol *matcher = SmartsToMol(sma); TEST_ASSERT(matcher); std::string smi = "n1c(C)oc(CC)c1"; ROMol *mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); ROMol *mol2 = replaceCore(*mol1, *matcher, true, true); TEST_ASSERT(mol2); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*]C.[3*]CC"); delete mol1; delete mol2; delete matcher; } { std::string sma = "n1cocc1"; ROMol *matcher = SmartsToMol(sma); TEST_ASSERT(matcher); std::string smi = "CCC1=C(OC)N=C(C)O1"; ROMol *mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); ROMol *mol2 = replaceCore(*mol1, *matcher, true, true); TEST_ASSERT(mol2); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*]C.[3*]CC.[4*]OC"); delete mol1; delete mol2; delete matcher; } { std::string sma = "n1cocc1"; ROMol *matcher = SmartsToMol(sma); TEST_ASSERT(matcher); std::string smi = "C1=C(OC)N=CO1"; ROMol *mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); ROMol *mol2 = replaceCore(*mol1, *matcher, true, true); TEST_ASSERT(mol2); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[4*]OC"); delete mol1; delete mol2; delete matcher; } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testReplaceCoreCrash() { ROMol *mol1 = 0, *mol2 = 0, *matcher1 = 0; std::string smi, sma; BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing a former crash in replaceCore" << std::endl; std::string pathName = getenv("RDBASE"); pathName += "/Code/GraphMol/ChemTransforms/testData/oldcrash.mol"; mol1 = MolFileToMol(pathName); TEST_ASSERT(mol1); sma = "N"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 6); smi = MolToSmiles(*mol2, true); // there's no way to guarantee the order here: TEST_ASSERT(smi == "[1*]CC.[2*]CC" || smi == "[2*]CC.[1*]CC"); BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testReplaceCorePositions() { ROMol *mol1 = 0, *mol2 = 0, *matcher1 = 0; std::string smi, sma; BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing that atom positions are correctly copied by replaceCore" << std::endl; std::string pathName = getenv("RDBASE"); pathName += "/Code/GraphMol/ChemTransforms/testData/core_location.mol"; mol1 = MolFileToMol(pathName); TEST_ASSERT(mol1); TEST_ASSERT(mol1->getNumAtoms() == 8); sma = "c1ccccc1"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); mol2 = replaceCore(*mol1, *matcher1); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 4); RDGeom::Point3D op, np; op = mol1->getConformer().getAtomPos(6); np = mol2->getConformer().getAtomPos(0); TEST_ASSERT(feq(op.x, np.x)); TEST_ASSERT(feq(op.y, np.y)); TEST_ASSERT(feq(op.z, np.z)); op = mol1->getConformer().getAtomPos(7); np = mol2->getConformer().getAtomPos(1); TEST_ASSERT(feq(op.x, np.x)); TEST_ASSERT(feq(op.y, np.y)); TEST_ASSERT(feq(op.z, np.z)); op = mol1->getConformer().getAtomPos(0); np = mol2->getConformer().getAtomPos(2); TEST_ASSERT(feq(op.x, np.x)); TEST_ASSERT(feq(op.y, np.y)); TEST_ASSERT(feq(op.z, np.z)); op = mol1->getConformer().getAtomPos(4); np = mol2->getConformer().getAtomPos(3); TEST_ASSERT(feq(op.x, np.x)); TEST_ASSERT(feq(op.y, np.y)); TEST_ASSERT(feq(op.z, np.z)); BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testMurckoDecomp() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing murcko decomposition" << std::endl; const char *testMolecules[][2] = { {"C1CC1CCC1CC(C)C1", "C1CC1CCC1CCC1"}, {"CC1CCC1", "C1CCC1"}, {"NCNCC2CC2C1CC1O", "C1CC1C1CC1"}, {"OC2C(C)C21C(N)C1C", "C2CC12CC1"}, // Spiro {"C1CC1C(=O)OC", "C1CC1"}, // Carbonyl outside scaffold {"C1CC1C=C", "C1CC1"}, // Double bond outside scaffold {"C1CC1C=CC1CC1C=CNNCO", "C1CC1C=CC1CC1"}, // Double bond in scaffold {"CC1CC1C(N)C1C(N)C1", "C1CC1CC1CC1"}, {"C1CC1S(=O)C1CC1C=CNNCO", "C1CC1S(=O)C1CC1"}, // S=O group in scaffold {"O=SCNC1CC1S(=O)C1CC1C=CNNCO", "C1CC1S(=O)C1CC1"}, // S=O group outside scaffold {"C1CC1S(=O)(=O)C1CC1C=CNNCO", "C1CC1S(=O)(=O)C1CC1"}, // SO2 group in scaffold {"O=S(CNCNC)(=O)CNC1CC1S(=O)(=O)C1CC1C=CNNCO", "C1CC1S(=O)(=O)C1CC1"}, // SO2 group outside scaffold {"C1CC1C=NO", "C1CC1"}, // Hydroxamide {"C1CC1C(C(C)C)=NC1CC1", "C1CC1C=NC1CC1"}, // Hydroxamide {"C1CC1C#N", "C1CC1"}, // Cyano group {"C1CC1C#CNC", "C1CC1"}, // Acetylene group {"O=C1N(C)C(=O)N1C#CNC", "O=C1NC(=O)N1"}, // Acetylene group {"[O-][N+](=O)c1cc(ccc1Cl)NS(=O)(=O)Cc2ccccc2", "c1ccccc1NS(=O)(=O)Cc2ccccc2"}, {"Cn1cccc1", "c1ccc[nH]1"}, {"C1CC1[CH](C)C1CC1", "C1CC1CC1CC1"}, {"CC(C)c1c(Cl)cc(F)c(Nc2ccc(C)cc2CC(=O)O)c1F", "c1ccc(Nc2ccccc2)cc1"}, {"C1CC1C[C@](Cl)(F)C1CCC1", "C1CC1CCC1CCC1"}, {"C1CC1.C1CC1", "C1CC1.C1CC1"}, // this was a crash at one point {"CCC", ""}, {"EOS", "EOS"}}; unsigned int i = 0; while (1) { std::string smi = testMolecules[i][0]; std::string tgt = testMolecules[i][1]; ++i; if (smi == "EOS") break; ROMol *mol = SmilesToMol(smi); ROMol *nMol = MurckoDecompose(*mol); TEST_ASSERT(nMol); delete mol; if (tgt != "") { TEST_ASSERT(nMol->getNumAtoms()); MolOps::sanitizeMol(static_cast(*nMol)); smi = MolToSmiles(*nMol, true); mol = SmilesToMol(tgt); TEST_ASSERT(mol); tgt = MolToSmiles(*mol, true); delete mol; TEST_ASSERT(smi == tgt); } else { TEST_ASSERT(nMol->getNumAtoms() == 0); } delete nMol; } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testReplaceCoreRequireDummies() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing replaceCore requiring dummy atoms" << std::endl; { std::string sma = "n1c(*)oc(*)c1"; ROMol *matcher = SmartsToMol(sma); TEST_ASSERT(matcher); std::string smi = "n1c(CC)oc(C)c1"; ROMol *mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); ROMol *mol2 = replaceCore(*mol1, *matcher, false, true, false); TEST_ASSERT(mol2); TEST_ASSERT(mol2->getNumAtoms() == 5); smi = MolToSmiles(*mol2, true); TEST_ASSERT(smi == "[1*]CC.[4*]C"); delete mol1; delete mol2; smi = "n1c(CC)oc(C)c1C"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); mol2 = replaceCore(*mol1, *matcher, false, true, true); TEST_ASSERT(!mol2); delete mol1; smi = "n1c(CC)occ1C"; mol1 = SmilesToMol(smi); TEST_ASSERT(mol1); mol2 = replaceCore(*mol1, *matcher, false, true, true); TEST_ASSERT(!mol2); delete mol1; delete matcher; } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testIssue3453144() { ROMol *mol1 = 0, *matcher1 = 0, *replacement = 0; std::string smi, sma; BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing that atom positions are correctly copied by replaceSubstructs" << std::endl; std::string pathName = getenv("RDBASE"); pathName += "/Code/GraphMol/ChemTransforms/testData/ethanol.mol"; mol1 = MolFileToMol(pathName); TEST_ASSERT(mol1); TEST_ASSERT(mol1->getNumAtoms() == 3); sma = "O"; matcher1 = SmartsToMol(sma); TEST_ASSERT(matcher1); smi = "N"; replacement = SmilesToMol(smi); TEST_ASSERT(replacement); std::vector rs; rs = replaceSubstructs(*mol1, *matcher1, *replacement); TEST_ASSERT(rs.size() == 1); TEST_ASSERT(rs[0]->getNumAtoms() == 3); TEST_ASSERT(rs[0]->getAtomWithIdx(2)->getAtomicNum() == 7); TEST_ASSERT(rs[0]->getNumConformers() == mol1->getNumConformers()); RDGeom::Point3D op, np; op = mol1->getConformer().getAtomPos(0); np = rs[0]->getConformer().getAtomPos(0); TEST_ASSERT(feq(op.x, np.x)); TEST_ASSERT(feq(op.y, np.y)); TEST_ASSERT(feq(op.z, np.z)); op = mol1->getConformer().getAtomPos(1); np = rs[0]->getConformer().getAtomPos(1); TEST_ASSERT(feq(op.x, np.x)); TEST_ASSERT(feq(op.y, np.y)); TEST_ASSERT(feq(op.z, np.z)); BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testIssue3537675() { std::string smi, sma; BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing handling of substituted non-carbon aromatic atoms" << std::endl; { std::string smi = "c1cccp1C"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); ROMol *nMol = MurckoDecompose(*mol); TEST_ASSERT(nMol->getAtomWithIdx(4)->getNumExplicitHs()); delete mol; delete nMol; } { std::string smi = "c1cccn1C"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); ROMol *nMol = MurckoDecompose(*mol); TEST_ASSERT(nMol->getAtomWithIdx(4)->getNumExplicitHs()); delete mol; delete nMol; } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testCombineMols() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing combination of molecules" << std::endl; { std::string smi1 = "C1CCC1"; std::string smi2 = "C1CC1"; ROMol *mol1 = SmilesToMol(smi1); ROMol *mol2 = SmilesToMol(smi2); ROMol *mol3 = combineMols(*mol1, *mol2); TEST_ASSERT(mol3->getNumAtoms() == (mol1->getNumAtoms() + mol2->getNumAtoms())); MolOps::findSSSR(*mol3); TEST_ASSERT(mol3->getRingInfo()->numRings() == 2); } { std::string pathName = getenv("RDBASE"); pathName += "/Code/GraphMol/ChemTransforms/testData/ethanol.mol"; ROMol *mol1 = MolFileToMol(pathName); TEST_ASSERT(mol1); ROMol *mol2 = MolFileToMol(pathName); TEST_ASSERT(mol2); TEST_ASSERT(mol1->getNumAtoms() == 3); TEST_ASSERT(mol2->getNumAtoms() == 3); ROMol *mol3 = combineMols(*mol1, *mol2); TEST_ASSERT(mol3->getNumAtoms() == (mol1->getNumAtoms() + mol2->getNumAtoms())); TEST_ASSERT(mol3->getNumConformers() == 1); TEST_ASSERT(feq(mol3->getConformer().getAtomPos(0).x, mol3->getConformer().getAtomPos(3).x)); TEST_ASSERT(feq(mol3->getConformer().getAtomPos(0).y, mol3->getConformer().getAtomPos(3).y)); TEST_ASSERT(feq(mol3->getConformer().getAtomPos(0).z, mol3->getConformer().getAtomPos(3).z)); delete mol3; mol3 = combineMols(*mol1, *mol2, RDGeom::Point3D(1, 0, 0)); TEST_ASSERT(mol3->getNumAtoms() == (mol1->getNumAtoms() + mol2->getNumAtoms())); TEST_ASSERT(mol3->getNumConformers() == 1); TEST_ASSERT(!feq(mol3->getConformer().getAtomPos(0).x, mol3->getConformer().getAtomPos(3).x)); TEST_ASSERT(feq(mol3->getConformer().getAtomPos(0).y, mol3->getConformer().getAtomPos(3).y)); TEST_ASSERT(feq(mol3->getConformer().getAtomPos(0).z, mol3->getConformer().getAtomPos(3).z)); } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testAddRecursiveQueries() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing adding recursive queries to a molecule" << std::endl; { std::string smi1 = "CC"; ROMol *mol1 = SmilesToMol(smi1); std::string smi2 = "CO"; ROMOL_SPTR q1(SmilesToMol(smi2)); std::map mp; mp["foo"] = q1; TEST_ASSERT(!mol1->getAtomWithIdx(0)->hasQuery()); addRecursiveQueries(*mol1, mp, "replaceme"); TEST_ASSERT(!mol1->getAtomWithIdx(0)->hasQuery()); mol1->getAtomWithIdx(0)->setProp("replaceme", "foo"); addRecursiveQueries(*mol1, mp, "replaceme"); TEST_ASSERT(mol1->getAtomWithIdx(0)->hasQuery()); TEST_ASSERT(mol1->getAtomWithIdx(0)->getQuery()->getDescription() == "AtomAnd"); TEST_ASSERT(!mol1->getAtomWithIdx(1)->hasQuery()); mol1->getAtomWithIdx(0)->setProp("replaceme", "bar"); bool ok = false; try { addRecursiveQueries(*mol1, mp, "replaceme"); } catch (KeyErrorException &e) { ok = true; } TEST_ASSERT(ok); delete mol1; } { std::string smi1 = "CC"; ROMol *mol1 = SmilesToMol(smi1); std::string smi2 = "CO"; ROMOL_SPTR q1(SmilesToMol(smi2)); std::map mp; mp["foo"] = q1; std::vector > labels; mol1->getAtomWithIdx(0)->setProp("replaceme", "foo"); addRecursiveQueries(*mol1, mp, "replaceme", &labels); TEST_ASSERT(mol1->getAtomWithIdx(0)->hasQuery()); TEST_ASSERT(labels.size() == 1); delete mol1; } { std::string smi1 = "CC"; ROMol *mol1 = SmilesToMol(smi1); std::string smi2 = "CO"; ROMOL_SPTR q1(SmilesToMol(smi2)); std::map mp; mp["foo"] = q1; smi2 = "OC"; ROMOL_SPTR q2(SmilesToMol(smi2)); mp["bar"] = q2; std::vector > labels; mol1->getAtomWithIdx(0)->setProp("replaceme", "foo"); mol1->getAtomWithIdx(1)->setProp("replaceme", "bar"); addRecursiveQueries(*mol1, mp, "replaceme", &labels); TEST_ASSERT(mol1->getAtomWithIdx(0)->hasQuery()); TEST_ASSERT(mol1->getAtomWithIdx(1)->hasQuery()); TEST_ASSERT(mol1->getAtomWithIdx(0)->getQuery()->getDescription() == "AtomAnd"); TEST_ASSERT(mol1->getAtomWithIdx(1)->getQuery()->getDescription() == "AtomAnd"); TEST_ASSERT(labels.size() == 2); delete mol1; } { std::string smi1 = "CC"; ROMol *mol1 = SmilesToMol(smi1); std::string smi2 = "CO"; ROMOL_SPTR q1(SmilesToMol(smi2)); std::map mp; mp["foo"] = q1; smi2 = "CN"; ROMOL_SPTR q2(SmilesToMol(smi2)); mp["bar"] = q2; mol1->getAtomWithIdx(0)->setProp("replaceme", "foo,bar"); addRecursiveQueries(*mol1, mp, "replaceme"); TEST_ASSERT(mol1->getAtomWithIdx(0)->hasQuery()); TEST_ASSERT(!mol1->getAtomWithIdx(1)->hasQuery()); TEST_ASSERT(mol1->getAtomWithIdx(0)->getQuery()->getDescription() == "AtomAnd"); MatchVectType mv; std::string msmi = "CCC"; ROMol *mmol = SmilesToMol(msmi); TEST_ASSERT(mmol); TEST_ASSERT(!SubstructMatch(*mmol, *mol1, mv)); delete mmol; msmi = "CCO"; mmol = SmilesToMol(msmi); TEST_ASSERT(mmol); TEST_ASSERT(SubstructMatch(*mmol, *mol1, mv)); delete mmol; msmi = "CCN"; mmol = SmilesToMol(msmi); TEST_ASSERT(mmol); TEST_ASSERT(SubstructMatch(*mmol, *mol1, mv)); delete mmol; delete mol1; } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testParseQueryDefFile() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing parsing query definition file" << std::endl; { std::string pathName = getenv("RDBASE"); pathName += "/Code/GraphMol/ChemTransforms/testData/query_file1.txt"; std::map qdefs; parseQueryDefFile(pathName, qdefs, false); TEST_ASSERT(!qdefs.empty()); TEST_ASSERT(qdefs.size() == 7); TEST_ASSERT(qdefs.find("AcidChloride") != qdefs.end()); TEST_ASSERT(qdefs.find("AcideChloride") == qdefs.end()); TEST_ASSERT(qdefs.find("AcidChloride.Aliphatic") != qdefs.end()); TEST_ASSERT(qdefs.find("CarboxylicAcid.AlphaAmino") != qdefs.end()); std::string msmi = "CCC(=O)Cl"; ROMol *mmol = SmilesToMol(msmi); TEST_ASSERT(mmol); MatchVectType mv; TEST_ASSERT(SubstructMatch(*mmol, *(qdefs["AcidChloride"]), mv)); delete mmol; } { std::string pathName = getenv("RDBASE"); pathName += "/Code/GraphMol/ChemTransforms/testData/query_file2.txt"; std::map qdefs; parseQueryDefFile(pathName, qdefs); TEST_ASSERT(qdefs.empty()); } /*{ std::string pathName = getenv("RDBASE"); pathName += "/Code/GraphMol/ChemTransforms/testData/query_file1.txt"; std::map qdefs; parseQueryDefFile(pathName, qdefs); TEST_ASSERT(!qdefs.empty()); TEST_ASSERT(qdefs.size()==7); TEST_ASSERT(qdefs.find("acidchloride")!=qdefs.end()); TEST_ASSERT(qdefs.find("AcidChloride")==qdefs.end()); }*/ BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testIssue275() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing sf.net issue 275: Murcko decomposition with chiral atoms" << std::endl; { std::string smi = "CCCCC[C@H]1CC[C@H](C(=O)O)CC1"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); ROMol *nMol = MurckoDecompose(*mol); smi = MolToSmiles(*nMol, true); TEST_ASSERT(smi == "C1CCCCC1"); delete mol; delete nMol; } { std::string smi = "CCCCC[C@H]1CC[C@H](C(=O)O)CC1"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); ROMol *nMol = MurckoDecompose(*mol); smi = MolToSmiles(*nMol, false); TEST_ASSERT(smi == "C1CCCCC1"); delete mol; delete nMol; } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testFragmentOnBonds() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing fragmentOnBonds" << std::endl; { std::string smi = "OCCCN"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms() == 5); unsigned int indices[] = {0, 3}; std::vector bindices( indices, indices + (sizeof(indices) / sizeof(indices[0]))); ROMol *nmol = MolFragmenter::fragmentOnBonds(*mol, bindices, false); TEST_ASSERT(nmol); TEST_ASSERT(nmol->getNumAtoms() == 5); delete mol; delete nmol; } { std::string smi = "OCCCN"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms() == 5); unsigned int indices[] = {0, 1}; std::vector bindices( indices, indices + (sizeof(indices) / sizeof(indices[0]))); std::vector cutsPerAtom(mol->getNumAtoms()); ROMol *nmol = MolFragmenter::fragmentOnBonds(*mol, bindices, false, 0, 0, &cutsPerAtom); TEST_ASSERT(nmol); TEST_ASSERT(nmol->getNumAtoms() == 5); TEST_ASSERT(cutsPerAtom[0] == 1); TEST_ASSERT(cutsPerAtom[1] == 2); TEST_ASSERT(cutsPerAtom[2] == 1); TEST_ASSERT(cutsPerAtom[3] == 0); delete mol; delete nmol; } { std::string smi = "OCCCN"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms() == 5); TEST_ASSERT(mol->getBondBetweenAtoms(0, 1)); TEST_ASSERT(mol->getBondBetweenAtoms(3, 4)); unsigned int indices[] = {0, 3}; std::vector bindices( indices, indices + (sizeof(indices) / sizeof(indices[0]))); ROMol *nmol = MolFragmenter::fragmentOnBonds(*mol, bindices); TEST_ASSERT(nmol); TEST_ASSERT(nmol->getNumAtoms() == 9); TEST_ASSERT(!nmol->getBondBetweenAtoms(0, 1)); TEST_ASSERT(!nmol->getBondBetweenAtoms(3, 4)); TEST_ASSERT(nmol->getAtomWithIdx(5)->getAtomicNum() == 0); TEST_ASSERT(nmol->getAtomWithIdx(5)->getIsotope() == 0); TEST_ASSERT(nmol->getBondBetweenAtoms(1, 5)); TEST_ASSERT(nmol->getAtomWithIdx(6)->getAtomicNum() == 0); TEST_ASSERT(nmol->getAtomWithIdx(6)->getIsotope() == 1); TEST_ASSERT(nmol->getBondBetweenAtoms(0, 6)); TEST_ASSERT(nmol->getAtomWithIdx(7)->getAtomicNum() == 0); TEST_ASSERT(nmol->getAtomWithIdx(7)->getIsotope() == 3); TEST_ASSERT(nmol->getBondBetweenAtoms(4, 7)); TEST_ASSERT(nmol->getAtomWithIdx(8)->getAtomicNum() == 0); TEST_ASSERT(nmol->getAtomWithIdx(8)->getIsotope() == 4); TEST_ASSERT(nmol->getBondBetweenAtoms(3, 8)); delete mol; delete nmol; } { std::string smi = "OCCCN"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms() == 5); TEST_ASSERT(mol->getBondBetweenAtoms(0, 1)); TEST_ASSERT(mol->getBondBetweenAtoms(3, 4)); unsigned int indices[] = {0, 3}; std::vector bindices( indices, indices + (sizeof(indices) / sizeof(indices[0]))); std::vector > dummyLabels(2); dummyLabels[0] = std::make_pair(10, 11); dummyLabels[1] = std::make_pair(100, 110); ROMol *nmol = MolFragmenter::fragmentOnBonds(*mol, bindices, true, &dummyLabels); TEST_ASSERT(nmol); TEST_ASSERT(nmol->getNumAtoms() == 9); TEST_ASSERT(!nmol->getBondBetweenAtoms(0, 1)); TEST_ASSERT(!nmol->getBondBetweenAtoms(3, 4)); TEST_ASSERT(nmol->getAtomWithIdx(5)->getAtomicNum() == 0); TEST_ASSERT(nmol->getAtomWithIdx(5)->getIsotope() == 10); TEST_ASSERT(nmol->getBondBetweenAtoms(1, 5)); TEST_ASSERT(nmol->getAtomWithIdx(6)->getAtomicNum() == 0); TEST_ASSERT(nmol->getAtomWithIdx(6)->getIsotope() == 11); TEST_ASSERT(nmol->getBondBetweenAtoms(0, 6)); TEST_ASSERT(nmol->getAtomWithIdx(7)->getAtomicNum() == 0); TEST_ASSERT(nmol->getAtomWithIdx(7)->getIsotope() == 100); TEST_ASSERT(nmol->getBondBetweenAtoms(4, 7)); TEST_ASSERT(nmol->getAtomWithIdx(8)->getAtomicNum() == 0); TEST_ASSERT(nmol->getAtomWithIdx(8)->getIsotope() == 110); TEST_ASSERT(nmol->getBondBetweenAtoms(3, 8)); delete mol; delete nmol; } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testFragmentOnBRICSBonds() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing fragmentOnBRICSBonds" << std::endl; { std::string smi = "c1ccccc1OC"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms() == 8); TEST_ASSERT(mol->getBondBetweenAtoms(5, 6)); TEST_ASSERT(mol->getBondBetweenAtoms(6, 7)); std::vector fbts; MolFragmenter::constructBRICSBondTypes(fbts); ROMol *nmol = MolFragmenter::fragmentOnBonds(*mol, fbts); TEST_ASSERT(nmol); TEST_ASSERT(nmol->getNumAtoms() == 10); TEST_ASSERT(!nmol->getBondBetweenAtoms(5, 6)); TEST_ASSERT(nmol->getBondBetweenAtoms(6, 7)); smi = MolToSmiles(*nmol, true); TEST_ASSERT(smi == "[16*]c1ccccc1.[3*]OC"); TEST_ASSERT(nmol->getAtomWithIdx(8)->getAtomicNum() == 0); TEST_ASSERT(nmol->getAtomWithIdx(8)->getIsotope() == 3); TEST_ASSERT(nmol->getBondBetweenAtoms(6, 8)); TEST_ASSERT(nmol->getAtomWithIdx(9)->getAtomicNum() == 0); TEST_ASSERT(nmol->getAtomWithIdx(9)->getIsotope() == 16); TEST_ASSERT(nmol->getBondBetweenAtoms(5, 9)); delete mol; delete nmol; } { std::string smi = "c1ccccc1"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms() == 6); std::vector fbts; MolFragmenter::constructBRICSBondTypes(fbts); ROMol *nmol = MolFragmenter::fragmentOnBonds(*mol, fbts); TEST_ASSERT(nmol); TEST_ASSERT(nmol->getNumAtoms() == 6); smi = MolToSmiles(*nmol, true); TEST_ASSERT(smi == "c1ccccc1"); delete mol; delete nmol; } { std::string smi = "OC(C)=CC"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms() == 5); std::vector fbts; MolFragmenter::constructBRICSBondTypes(fbts); ROMol *nmol = MolFragmenter::fragmentOnBonds(*mol, fbts); TEST_ASSERT(nmol); TEST_ASSERT(nmol->getNumAtoms() == 7); smi = MolToSmiles(*nmol, true); TEST_ASSERT(smi == "[7*]=C(C)O.[7*]=CC"); delete mol; delete nmol; } { std::string smi = "c1ccccc1OC"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms() == 8); ROMol *nmol = MolFragmenter::fragmentOnBRICSBonds(*mol); TEST_ASSERT(nmol); TEST_ASSERT(nmol->getNumAtoms() == 10); smi = MolToSmiles(*nmol, true); TEST_ASSERT(smi == "[16*]c1ccccc1.[3*]OC"); delete mol; delete nmol; } { std::string smi = "OC(C)=CC"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms() == 5); ROMol *nmol = MolFragmenter::fragmentOnBRICSBonds(*mol); TEST_ASSERT(nmol); TEST_ASSERT(nmol->getNumAtoms() == 7); smi = MolToSmiles(*nmol, true); TEST_ASSERT(smi == "[7*]=C(C)O.[7*]=CC"); delete mol; delete nmol; } { std::string smi = "CCCOCCC(=O)c1ccccc1"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms() == 14); ROMol *nmol = MolFragmenter::fragmentOnBRICSBonds(*mol); TEST_ASSERT(nmol); TEST_ASSERT(nmol->getNumAtoms() == 20); smi = MolToSmiles(*nmol, true); TEST_ASSERT(smi == "[16*]c1ccccc1.[3*]O[3*].[4*]CCC.[4*]CCC([6*])=O"); MolOps::sanitizeMol(static_cast(*nmol)); smi = MolToSmiles(*nmol, true); TEST_ASSERT(smi == "[16*]c1ccccc1.[3*]O[3*].[4*]CCC.[4*]CCC([6*])=O"); delete mol; delete nmol; } { std::string smi = "Cl.CC(=O)O[C@]1(c2ccccc2)CCN(C)[C@H]2CCCC[C@@H]21"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms() == 22); ROMol *nmol = MolFragmenter::fragmentOnBRICSBonds(*mol); TEST_ASSERT(nmol); TEST_ASSERT(nmol->getNumAtoms() == 28); smi = MolToSmiles(*nmol, true); // std::cerr<(*nmol)); smi = MolToSmiles(*nmol, true); TEST_ASSERT(smi == "Cl.[1*]C(C)=O.[15*]C1([15*])CCN(C)[C@H]2CCCC[C@@H]21.[16*]" "c1ccccc1.[3*]O[3*]"); delete mol; delete nmol; } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void benchFragmentOnBRICSBonds() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing fragmentOnBRICSBonds" << std::endl; { std::string pathName = getenv("RDBASE"); pathName += "/Regress/Data/mols.1000.sdf"; SDMolSupplier suppl(pathName); while (!suppl.atEnd()) { ROMol *m = suppl.next(); ROMol *nmol = MolFragmenter::fragmentOnBRICSBonds(*m); delete m; delete nmol; } } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testFragmentOnSomeBonds() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing fragmentOnSomeBonds" << std::endl; { std::string smi = "OCCCCN"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms()); unsigned int indices[] = {0, 2, 4}; std::vector bindices( indices, indices + (sizeof(indices) / sizeof(indices[0]))); std::vector frags; MolFragmenter::fragmentOnSomeBonds(*mol, bindices, frags, 2); TEST_ASSERT(frags.size() == 3); std::vector > fragMap; TEST_ASSERT(MolOps::getMolFrags(*frags[0], fragMap) == 3); TEST_ASSERT(fragMap.size() == 3); TEST_ASSERT(fragMap[0].size() == 2); TEST_ASSERT(fragMap[1].size() == 4); TEST_ASSERT(fragMap[2].size() == 4); TEST_ASSERT(MolOps::getMolFrags(*frags[1], fragMap) == 3); TEST_ASSERT(fragMap.size() == 3); TEST_ASSERT(fragMap[0].size() == 2); TEST_ASSERT(fragMap[1].size() == 6); TEST_ASSERT(fragMap[2].size() == 2); TEST_ASSERT(MolOps::getMolFrags(*frags[2], fragMap) == 3); TEST_ASSERT(fragMap.size() == 3); TEST_ASSERT(fragMap[0].size() == 4); TEST_ASSERT(fragMap[1].size() == 4); TEST_ASSERT(fragMap[2].size() == 2); delete mol; } { std::string smi = "OCCCCN"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms()); unsigned int indices[] = {0, 2, 4}; std::vector bindices( indices, indices + (sizeof(indices) / sizeof(indices[0]))); std::vector frags; std::vector > cpa; MolFragmenter::fragmentOnSomeBonds(*mol, bindices, frags, 2, false, NULL, NULL, &cpa); TEST_ASSERT(frags.size() == 3); TEST_ASSERT(cpa.size() == 3); TEST_ASSERT(cpa[0].size() == mol->getNumAtoms()); TEST_ASSERT(cpa[1].size() == mol->getNumAtoms()); TEST_ASSERT(cpa[2].size() == mol->getNumAtoms()); delete mol; } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testGithubIssue429() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing github issue 429: fragmentOnSomeBonds() " "should update implicit H count on aromatic " "heteroatoms when addDummies is False" << std::endl; { std::string smi = "c1cccn1CC1CC1"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms()); unsigned int indices[] = {4, 5}; std::vector bindices( indices, indices + (sizeof(indices) / sizeof(indices[0]))); std::vector frags; MolFragmenter::fragmentOnSomeBonds(*mol, bindices, frags, 1, false); TEST_ASSERT(frags.size() == 2); std::vector > fragMap; BOOST_FOREACH (ROMOL_SPTR romol, frags) { RWMol *rwmol = (RWMol *)(romol.get()); MolOps::sanitizeMol(*rwmol); } // we actually changed fragmentOnBonds(), check that too: RWMol *nmol = (RWMol *)MolFragmenter::fragmentOnBonds(*mol, bindices, false); MolOps::sanitizeMol(*nmol); delete nmol; delete mol; } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } void testGithubIssue430() { BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdInfoLog) << "Testing github issue 430: fragmentOnSomeBonds() " "crashes if bond list is empty" << std::endl; { std::string smi = "c1cccn1CC1CC1"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms()); std::vector bindices; std::vector frags; MolFragmenter::fragmentOnSomeBonds(*mol, bindices, frags, 1, false); TEST_ASSERT(frags.size() == 0); delete mol; } { std::string smi = "c1cccn1CC1CC1"; RWMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); TEST_ASSERT(mol->getNumAtoms()); unsigned int indices[] = {4, 5}; std::vector bindices( indices, indices + (sizeof(indices) / sizeof(indices[0]))); std::vector frags; MolFragmenter::fragmentOnSomeBonds(*mol, bindices, frags, 0, false); TEST_ASSERT(frags.size() == 0); delete mol; } BOOST_LOG(rdInfoLog) << "\tdone" << std::endl; } int main() { RDLog::InitLogs(); BOOST_LOG(rdInfoLog) << "********************************************************\n"; BOOST_LOG(rdInfoLog) << "Testing Chemical Transforms \n"; #if 1 testDeleteSubstruct(); testReplaceSubstructs(); testReplaceSubstructs2(); testReplaceSidechains(); testReplaceCore(); testReplaceCoreLabels(); testReplaceCoreCrash(); testReplaceCorePositions(); testMurckoDecomp(); testReplaceCoreRequireDummies(); testIssue3453144(); testIssue3537675(); testCombineMols(); testAddRecursiveQueries(); testParseQueryDefFile(); testIssue275(); testFragmentOnBonds(); testFragmentOnBRICSBonds(); #endif testFragmentOnSomeBonds(); // benchFragmentOnBRICSBonds(); testGithubIssue429(); testGithubIssue430(); BOOST_LOG(rdInfoLog) << "*******************************************************\n"; return (0); }