// $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< std::pair > 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); }