diff --git a/External/CoordGen/CMakeLists.txt b/External/CoordGen/CMakeLists.txt index beeecb4e6..7ad5b0845 100644 --- a/External/CoordGen/CMakeLists.txt +++ b/External/CoordGen/CMakeLists.txt @@ -82,24 +82,24 @@ if(RDK_BUILD_COORDGEN_SUPPORT) endif() if(NOT EXISTS "${COORDGEN_DIR}/sketcherMinimizer.h") - set(RELEASE_NO "1.4.1") - set(MD5 "d9a925c9569bc08e241a01669f43d639") + set(RELEASE_NO "1.4.2") + set(MD5 "47aa5fe6d8186b6c8d3b871d4400218a") downloadAndCheckMD5("https://github.com/schrodinger/coordgenlibs/archive/v${RELEASE_NO}.tar.gz" "${CMAKE_CURRENT_SOURCE_DIR}/coordgenlibs-${RELEASE_NO}.tar.gz" ${MD5}) execute_process(COMMAND ${CMAKE_COMMAND} -E tar zxf ${CMAKE_CURRENT_SOURCE_DIR}/coordgenlibs-${RELEASE_NO}.tar.gz WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - # FIX: this is a workaround until https://github.com/schrodinger/coordgenlibs/pull/76 - # is merged and a new coordgen release is done file(RENAME "coordgenlibs-${RELEASE_NO}" "${COORDGEN_DIR}") - set(fileToPatch "${COORDGEN_DIR}/CoordgenFragmenter.h") - configure_file("${fileToPatch}" "${fileToPatch}.orig" COPYONLY) - file(READ "${fileToPatch}" buffer) - string(REPLACE "class CoordgenFragmenter" - "#include \"CoordgenConfig.hpp\"\nclass EXPORT_COORDGEN CoordgenFragmenter" - buffer "${buffer}") - file(WRITE "${fileToPatch}" "${buffer}") + # # FIX: this is a workaround until https://github.com/schrodinger/coordgenlibs/pull/76 + # # is merged and a new coordgen release is done + # set(fileToPatch "${COORDGEN_DIR}/CoordgenFragmenter.h") + # configure_file("${fileToPatch}" "${fileToPatch}.orig" COPYONLY) + # file(READ "${fileToPatch}" buffer) + # string(REPLACE "class CoordgenFragmenter" + # "#include \"CoordgenConfig.hpp\"\nclass EXPORT_COORDGEN CoordgenFragmenter" + # buffer "${buffer}") + # file(WRITE "${fileToPatch}" "${buffer}") else() message("-- Found coordgenlibs source in ${COORDGEN_DIR}") endif() diff --git a/External/CoordGen/CoordGen.h b/External/CoordGen/CoordGen.h index e6a02c77c..fd84119d8 100644 --- a/External/CoordGen/CoordGen.h +++ b/External/CoordGen/CoordGen.h @@ -34,10 +34,12 @@ struct CoordGenParams { // length of 50. std::string templateFileDir = ""; float minimizerPrecision = - sketcherCoarsePrecision; // controls sketch precision - bool dbg_useConstrained = true; // debugging - bool dbg_useFixed = false; // debugging - bool minimizeOnly = false; // don't actually generate full coords + sketcherCoarsePrecision; // controls sketch precision + bool dbg_useConstrained = true; // debugging + bool dbg_useFixed = false; // debugging + bool minimizeOnly = false; // don't actually generate full coords + bool treatBondsToMetalAsZeroOrder = + false; // set all bonds to metal atoms to be zero-order bonds }; static CoordGenParams defaultParams; @@ -75,6 +77,8 @@ unsigned int addCoords(T& mol, const CoordGenParams* params = nullptr) { sketcherMinimizer minimizer(params->minimizerPrecision); auto min_mol = new sketcherMinimizerMolecule(); + minimizer.setTreatAllBondsToMetalAsZOBs(params->treatBondsToMetalAsZeroOrder); + // FIX: only do this check once. // std::cerr << " TEMPLATES: " << templateFileDir << std::endl; if (templateFileDir != "") { diff --git a/External/CoordGen/Wrap/rdCoordGen.cpp b/External/CoordGen/Wrap/rdCoordGen.cpp index c07ae7563..ff6b8d3d4 100644 --- a/External/CoordGen/Wrap/rdCoordGen.cpp +++ b/External/CoordGen/Wrap/rdCoordGen.cpp @@ -73,21 +73,26 @@ struct coordgen_wrapper { "uses coordgen's force field to cleanup the 2D " "coordinates of the active conformation") .def_readonly("sketcherBestPrecision", - &CoordGen::CoordGenParams::sketcherBestPrecision, - "highest quality (and slowest) precision setting") + &CoordGen::CoordGenParams::sketcherBestPrecision, + "highest quality (and slowest) precision setting") .def_readonly("sketcherStandardPrecision", - &CoordGen::CoordGenParams::sketcherStandardPrecision, - "standard quality precision setting, the default for the coordgen project") + &CoordGen::CoordGenParams::sketcherStandardPrecision, + "standard quality precision setting, the default for the " + "coordgen project") .def_readonly("sketcherQuickPrecision", - &CoordGen::CoordGenParams::sketcherQuickPrecision, - "faster precision setting") - .def_readonly("sketcherCoarsePrecision", - &CoordGen::CoordGenParams::sketcherCoarsePrecision, - "\"coarse\" (fastest) precision setting, produces good-quality coordinates" - " most of the time, this is the default setting for the RDKit") + &CoordGen::CoordGenParams::sketcherQuickPrecision, + "faster precision setting") + .def_readonly( + "sketcherCoarsePrecision", + &CoordGen::CoordGenParams::sketcherCoarsePrecision, + "\"coarse\" (fastest) precision setting, produces good-quality " + "coordinates" + " most of the time, this is the default setting for the RDKit") .def_readwrite("minimizerPrecision", &CoordGen::CoordGenParams::minimizerPrecision, - "controls sketcher precision"); + "controls sketcher precision") + .def_readwrite("treatBondsToMetalAsZOBs", + &CoordGen::CoordGenParams::treatBondsToMetalAsZeroOrder); python::def("SetDefaultTemplateFileDir", SetDefaultTemplateFileDir); docString = "Add 2D coordinates.\n" diff --git a/External/CoordGen/test.cpp b/External/CoordGen/test.cpp index c3d2c6595..9a49f8290 100644 --- a/External/CoordGen/test.cpp +++ b/External/CoordGen/test.cpp @@ -559,6 +559,69 @@ M END BOOST_LOG(rdInfoLog) << "done" << std::endl; } +void testZOBs() { + BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; + BOOST_LOG(rdInfoLog) << "testing the zero-order bond setting with coordgen" + << std::endl; + { + auto m1 = + R"CTAB( + RDKit 2D + + 0 0 0 0 0 0 0 0 0 0999 V3000 +M V30 BEGIN CTAB +M V30 COUNTS 8 7 0 0 0 +M V30 BEGIN ATOM +M V30 1 Al 0.108450 -0.062175 0.000000 0 VAL=3 +M V30 2 C 0.976250 -0.558975 0.000000 0 +M V30 3 C 0.104850 0.937825 0.000000 0 +M V30 4 C -0.755750 -0.565175 0.000000 0 +M V30 5 C 1.840650 -0.055775 0.000000 0 +M V30 6 C -1.623550 -0.068375 0.000000 0 +M V30 7 C -2.487750 -0.571375 0.000000 0 +M V30 8 C 1.836850 0.944025 0.000000 0 +M V30 END ATOM +M V30 BEGIN BOND +M V30 1 1 1 2 +M V30 2 1 1 3 +M V30 3 1 1 4 +M V30 4 2 2 5 +M V30 5 2 4 6 +M V30 6 1 6 7 +M V30 7 1 5 8 +M V30 END BOND +M V30 END CTAB +M END +)CTAB"_ctab; + TEST_ASSERT(m1); + TEST_ASSERT(m1->getNumConformers() == 1); + CoordGen::addCoords(*m1); + TEST_ASSERT(m1->getNumConformers() == 1); + { + std::unique_ptr nm{MolBlockToMol(MolToMolBlock(*m1))}; + TEST_ASSERT(nm); + TEST_ASSERT(nm->getBondWithIdx(3)->getStereo() == + m1->getBondWithIdx(3)->getStereo()); + TEST_ASSERT(nm->getBondWithIdx(4)->getStereo() == + m1->getBondWithIdx(4)->getStereo()); + } + + CoordGen::CoordGenParams ps; + ps.treatBondsToMetalAsZeroOrder = true; + CoordGen::addCoords(*m1, &ps); + { + // the ZOB behavior screws up the double bond stereo here... detect that + std::unique_ptr nm{MolBlockToMol(MolToMolBlock(*m1))}; + TEST_ASSERT(nm); + TEST_ASSERT(nm->getBondWithIdx(3)->getStereo() != + m1->getBondWithIdx(3)->getStereo()); + TEST_ASSERT(nm->getBondWithIdx(4)->getStereo() != + m1->getBondWithIdx(4)->getStereo()); + } + } + BOOST_LOG(rdInfoLog) << "done" << std::endl; +} + int main(int argc, char* argv[]) { (void)argc; (void)argv; @@ -570,4 +633,5 @@ int main(int argc, char* argv[]) { testGithub3131(); #endif testCoordgenMinimize(); + testZOBs(); }