// $Id$ // // Copyright (C) 2003-2006 Rational Discovery LLC // // @@ 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 "FragCatGenerator.h" #include "FragCatalogEntry.h" #include "FragCatParams.h" #include "FragCatalogUtils.h" #include "FragFPGenerator.h" #include #include #include #include #include #include #include #include using namespace RDKit; void testMols(std::vector> &mols, FragFPGenerator &fpGen, FragCatalog &fcat) { int nDone = 0; for (auto &&mi : mols) { ExplicitBitVect *fp = fpGen.getFPForMol(*mi, fcat); switch (nDone) { case 0: TEST_ASSERT(fp->getNumOnBits() == 3); TEST_ASSERT((*fp)[0]); TEST_ASSERT((*fp)[1]); TEST_ASSERT((*fp)[2]); break; case 1: TEST_ASSERT(fp->getNumOnBits() == 2); TEST_ASSERT((*fp)[1]); TEST_ASSERT((*fp)[3]); break; case 2: TEST_ASSERT(fp->getNumOnBits() == 3); TEST_ASSERT((*fp)[1]); TEST_ASSERT((*fp)[4]); TEST_ASSERT((*fp)[5]); break; case 3: TEST_ASSERT(fp->getNumOnBits() == 3); TEST_ASSERT((*fp)[1]); TEST_ASSERT((*fp)[6]); TEST_ASSERT((*fp)[7]); break; case 4: TEST_ASSERT(fp->getNumOnBits() == 2); TEST_ASSERT((*fp)[0]); TEST_ASSERT((*fp)[8]); break; case 5: TEST_ASSERT(fp->getNumOnBits() == 3); TEST_ASSERT((*fp)[0]); TEST_ASSERT((*fp)[6]); TEST_ASSERT((*fp)[9]); break; case 6: TEST_ASSERT(fp->getNumOnBits() == 5); TEST_ASSERT((*fp)[0]); TEST_ASSERT((*fp)[1]); TEST_ASSERT((*fp)[2]); TEST_ASSERT((*fp)[3]); TEST_ASSERT((*fp)[10]); break; } delete fp; nDone += 1; } } void test1() { std::string rdbase = getenv("RDBASE"); std::string fname = rdbase + "/Code/GraphMol/FragCatalog/test_data/mols.smi"; std::string fgrpFile = rdbase + "/Code/GraphMol/FragCatalog/test_data/funcGroups.txt"; SmilesMolSupplier suppl(fname, " ", 0, 1, false); auto *fparams = new FragCatParams(1, 6, fgrpFile, 1.0e-8); TEST_ASSERT(fparams->getNumFuncGroups() == 15); FragCatalog fcat(fparams); FragCatGenerator catGen; std::vector> mols; unsigned int nDone = 0; ROMol *m = suppl.next(); while (m) { mols.push_back(std::unique_ptr(m)); nDone += 1; catGen.addFragsFromMol(*m, &fcat); try { m = suppl.next(); } catch (FileParseException &) { m = nullptr; } } TEST_ASSERT(mols.size() == 16); TEST_ASSERT(nDone == 16); int nents = fcat.getNumEntries(); std::cerr << " " << nents << std::endl; TEST_ASSERT(nents == 21); FragFPGenerator fpGen; BOOST_LOG(rdInfoLog) << "----- Test 1" << std::endl; testMols(mols, fpGen, fcat); BOOST_LOG(rdInfoLog) << "---- Done" << std::endl; //---------------------------------------------------------- // SERIALIZATION TESTS //---------------------------------------------------------- // make sure we can pickle and unpickle parameter objects: FragCatParams newParams; std::string pickle = fparams->Serialize(); newParams.initFromString(pickle); TEST_ASSERT(newParams.getLowerFragLength() == fparams->getLowerFragLength()); TEST_ASSERT(newParams.getUpperFragLength() == fparams->getUpperFragLength()); TEST_ASSERT(newParams.getTolerance() == fparams->getTolerance()); TEST_ASSERT(newParams.getNumFuncGroups() == fparams->getNumFuncGroups()); // make sure we can pickle and unpickle catalog entries: const FragCatalogEntry *fpEntry = fcat.getEntryWithIdx(0); auto *fpEntry2 = new FragCatalogEntry(); fpEntry2->initFromString(fpEntry->Serialize()); TEST_ASSERT(fpEntry->getDescription() == fpEntry2->getDescription()); TEST_ASSERT(fpEntry->getOrder() == fpEntry2->getOrder()); TEST_ASSERT(fpEntry->getBitId() == fpEntry2->getBitId()); TEST_ASSERT(fpEntry2->match(fpEntry, 1e-8)); TEST_ASSERT(fpEntry->match(fpEntry2, 1e-8)); delete fpEntry2; // test catalogs' initFromString: FragCatalog fcat2; fcat2.initFromString(fcat.Serialize()); TEST_ASSERT(fcat2.getNumEntries() == fcat.getNumEntries()); BOOST_LOG(rdInfoLog) << "----- Test 2" << std::endl; testMols(mols, fpGen, fcat2); BOOST_LOG(rdInfoLog) << "---- Done" << std::endl; // and the pickle ctor: FragCatalog *fcat3 = new FragCatalog(fcat.Serialize()); TEST_ASSERT(fcat3->getNumEntries() == fcat.getNumEntries()); BOOST_LOG(rdInfoLog) << "----- Test 3" << std::endl; testMols(mols, fpGen, *fcat3); BOOST_LOG(rdInfoLog) << "---- Done" << std::endl; //---------------------------------------------------------- // test issue 115 //---------------------------------------------------------- BOOST_LOG(rdInfoLog) << "----- Test Issue 115" << std::endl; delete fparams; fparams = new FragCatParams(3, 3, fgrpFile, 1.0e-8); TEST_ASSERT(fparams->getNumFuncGroups() == 15); delete fcat3; fcat3 = new FragCatalog(fparams); suppl.reset(); nDone = 0; while (!suppl.atEnd()) { nDone++; ROMol *m = suppl.next(); catGen.addFragsFromMol(*m, fcat3); delete m; } TEST_ASSERT(nDone == suppl.length()); TEST_ASSERT(fcat3->getNumEntries() == 21); TEST_ASSERT(fcat3->getFPLength() == 10); for (unsigned int i = 0; i < fcat3->getFPLength(); i++) { TEST_ASSERT(fcat3->getEntryWithBitId(i)->getOrder() == 3); } BOOST_LOG(rdInfoLog) << "---- Done" << std::endl; //---------------------------------------------------------- // test issue 117 //---------------------------------------------------------- BOOST_LOG(rdInfoLog) << "----- Test Issue 117" << std::endl; delete fparams; fparams = new FragCatParams(1, 2, fgrpFile, 1.0e-8); delete fcat3; fcat3 = new FragCatalog(fparams); ROMol *tmpMol = SmilesToMol("OC(N)CO"); TEST_ASSERT(tmpMol); catGen.addFragsFromMol(*tmpMol, fcat3); TEST_ASSERT(fcat3->getNumEntries() == 1); // std::cout << fcat3->getEntryWithBitId(0)->getDescription() << std::endl; TEST_ASSERT(fcat3->getEntryWithBitId(0)->getDescription() == "C(<-O>)<-N>C<-O>"); BOOST_LOG(rdInfoLog) << "---- Done" << std::endl; delete tmpMol; delete fparams; delete fcat3; } void testIssue294() { BOOST_LOG(rdInfoLog) << "---- Test Issue294\n Watch memory usage." << std::endl; std::string rdbase = getenv("RDBASE"); std::string fname = rdbase + "/Code/GraphMol/FragCatalog/test_data/mols.smi"; std::string fgrpFile = rdbase + "/Code/GraphMol/FragCatalog/test_data/funcGroups.txt"; SmilesMolSupplier suppl(fname, " ", 0, 1, false); auto *fparams = new FragCatParams(1, 6, fgrpFile, 1.0e-8); FragCatalog fcat(fparams); FragCatGenerator catGen; std::vector> mols; ROMol *m = suppl.next(); while (m) { mols.push_back(std::unique_ptr(m)); catGen.addFragsFromMol(*m, &fcat); try { m = suppl.next(); } catch (FileParseException &) { m = nullptr; } } int nents = fcat.getNumEntries(); TEST_ASSERT(nents == 21); FragFPGenerator fpGen; for (unsigned int i = 0; i < 200; i++) { for (auto &&mi : mols) { ExplicitBitVect *fp = fpGen.getFPForMol(*mi, fcat); delete fp; } } delete fparams; BOOST_LOG(rdInfoLog) << "---- Done" << std::endl; } void testWhiteSpaceInSmarts() { BOOST_LOG(rdInfoLog) << "----- Test Whitespace in SMARTS Fragment string." << std::endl; std::vector data( {" ", // whitespace only " \n", // whitespace plus new line " // initial space plus comment\nfluorine\t[F]\n"}); std::vector reference_sizes({0, 0, 1}); auto reference = reference_sizes.cbegin(); for (const auto &smarts : data) { std::istringstream input(smarts); auto groups = readFuncGroups(input); TEST_ASSERT(groups.size() == *reference); ++reference; } BOOST_LOG(rdInfoLog) << "---- Done" << std::endl; } void testFragmentWithoutSmarts() { BOOST_LOG(rdInfoLog) << "----- Test Fragment string without SMARTS." << std::endl; std::vector data( {"// Name SMARTS\nnonsense\n", "// Name SMARTS\nnonsense no new line", "// Name SMARTS\nnonsense with tab\t\n"}); for (const auto &smarts : data) { bool ok = false; std::istringstream input(smarts); RDKit::MOL_SPTR_VECT groups; try { groups = readFuncGroups(input); } catch (const Invar::Invariant &) { ok = true; } TEST_ASSERT(ok); TEST_ASSERT(groups.empty()); } BOOST_LOG(rdInfoLog) << "---- Done" << std::endl; } int main() { RDLog::InitLogs(); test1(); testIssue294(); testWhiteSpaceInSmarts(); testFragmentWithoutSmarts(); return 0; }