diff --git a/CMakeLists.txt b/CMakeLists.txt index 812f3f8a098..455f05c0e75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,7 @@ option(RDK_BUILD_FUZZ_TARGETS "build the fuzz targets" OFF) option(RDK_BUILD_MINIMAL_LIB_RXN "build support for reactions into MinimalLib" ON ) option(RDK_BUILD_MINIMAL_LIB_SUBSTRUCTLIBRARY "build support for SubstructLibrary into MinimalLib" ON ) option(RDK_BUILD_MINIMAL_LIB_MCS "build support for MCS into MinimalLib" OFF ) +option(RDK_BUILD_MINIMAL_LIB_ZIP "build support for fragment linkage into MinimalLib" OFF ) set(RDK_BOOST_VERSION "1.70.0") diff --git a/Code/GraphMol/ChemTransforms/MolFragmenter.cpp b/Code/GraphMol/ChemTransforms/MolFragmenter.cpp index 212671ac154..32ce46ca4a6 100644 --- a/Code/GraphMol/ChemTransforms/MolFragmenter.cpp +++ b/Code/GraphMol/ChemTransforms/MolFragmenter.cpp @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -1172,5 +1174,55 @@ std::unique_ptr molzip(const std::map &row, return molzip(mols, params); } +void parseMolzipParametersJSON(const char* json, MolzipParams* params) { + if (!params || !json || !strlen(json)) + return; + + std::istringstream ss; + ss.str(json); + boost::property_tree::ptree pt; + boost::property_tree::read_json(ss, pt); + + auto& p = *params; + std::string label = pt.get("Label", ""); + if (label == "AtomMapNumber") + p.label = MolzipLabel::AtomMapNumber; + else if (label == "Isotope") + p.label = MolzipLabel::Isotope; + else if (label == "FragmentOnBonds") + p.label = MolzipLabel::FragmentOnBonds; + else if (label == "AtomType") + p.label = MolzipLabel::AtomType; + else if (label == "AtomProperty") + p.label = MolzipLabel::AtomProperty; + else if (label != "") + throw ValueErrorException("Unknown label"); + + std::string atomSymbolsRow = pt.get("AtomSymbols", ""); + + if (atomSymbolsRow != "") { + std::string::iterator it = atomSymbolsRow.begin(); + std::vector atomSymbols; + std::string atomSymbol = ""; + + for (; it != atomSymbolsRow.end(); ++it) { + if (*it == ',') { + atomSymbols.push_back(atomSymbol); + atomSymbol = ""; + } + else + atomSymbol += *it; + if (next(it) == atomSymbolsRow.end()) + atomSymbols.push_back(atomSymbol); + } + + p.atomSymbols = atomSymbols; + } + + p.atomProperty = pt.get("AtomProperty", p.atomProperty); + p.enforceValenceRules = pt.get("EnforceValenceRules", p.enforceValenceRules); + p.generateCoordinates = pt.get("GenerateCoordinates", p.generateCoordinates); +} + } // end of namespace RDKit diff --git a/Code/GraphMol/ChemTransforms/MolFragmenter.h b/Code/GraphMol/ChemTransforms/MolFragmenter.h index 6a38fa9a443..0ebb976834d 100644 --- a/Code/GraphMol/ChemTransforms/MolFragmenter.h +++ b/Code/GraphMol/ChemTransforms/MolFragmenter.h @@ -156,5 +156,8 @@ RDKIT_CHEMTRANSFORMS_EXPORT std::unique_ptr molzip( */ RDKIT_CHEMTRANSFORMS_EXPORT std::unique_ptr molzip(const std::map &row, const MolzipParams ¶ms=MolzipParams()); + +RDKIT_CHEMTRANSFORMS_EXPORT void parseMolzipParametersJSON(const char* json, + MolzipParams* params); } // namespace RDKit #endif diff --git a/Code/MinimalLib/CMakeLists.txt b/Code/MinimalLib/CMakeLists.txt index 3d02a261893..17fdbe170b0 100644 --- a/Code/MinimalLib/CMakeLists.txt +++ b/Code/MinimalLib/CMakeLists.txt @@ -26,7 +26,11 @@ if(RDK_BUILD_MINIMAL_LIB) if(RDK_BUILD_MINIMAL_LIB_MMPA) add_definitions(-DRDK_BUILD_MINIMAL_LIB_MMPA) set(MINIMAL_LIB_LIBRARIES "${MINIMAL_LIB_LIBRARIES};MMPA_static") - endif() + endif() + if(DRDK_BUILD_MINIMAL_LIB_ZIP) + add_definitions(-DRDK_BUILD_MINIMAL_LIB_ZIP) + set(MINIMAL_LIB_LIBRARIES "${MINIMAL_LIB_LIBRARIES};ChemTransforms_static") + endif() if(RDK_BUILD_FREETYPE_SUPPORT) if( ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten") set(USE_FLAGS "-s USE_FREETYPE=1") diff --git a/Code/MinimalLib/jswrapper.cpp b/Code/MinimalLib/jswrapper.cpp index 79803949e0f..371c1b92cd3 100644 --- a/Code/MinimalLib/jswrapper.cpp +++ b/Code/MinimalLib/jswrapper.cpp @@ -140,6 +140,12 @@ std::string get_mcs_as_smarts_no_details(const JSMolList &mols) { } #endif +#ifdef RDK_BUILD_MINIMAL_LIB_ZIP +JSMol * get_molzip_no_details(const JSMol &a, const JSMol &b) { + return get_molzip(a, b, std::string()); +} +#endif + emscripten::val binary_string_to_uint8array(const std::string &pkl) { emscripten::val view(emscripten::typed_memory_view( pkl.size(), reinterpret_cast(pkl.c_str()))); @@ -672,4 +678,8 @@ EMSCRIPTEN_BINDINGS(RDKit_minimal) { function("get_mcs_as_smarts", &get_mcs_as_smarts); function("get_mcs_as_smarts", &get_mcs_as_smarts_no_details); #endif +#ifdef RDK_BUILD_MINIMAL_LIB_ZIP + function("link", &get_molzip, allow_raw_pointers()); + function("link", &get_molzip_no_details, allow_raw_pointers()); +#endif } diff --git a/Code/MinimalLib/minilib.cpp b/Code/MinimalLib/minilib.cpp index 964a5baa665..3cd047c23bb 100644 --- a/Code/MinimalLib/minilib.cpp +++ b/Code/MinimalLib/minilib.cpp @@ -30,6 +30,10 @@ #ifdef RDK_BUILD_MINIMAL_LIB_MCS #include #endif +#ifdef RDK_BUILD_MINIMAL_LIB_ZIP +#include +#endif + #include #include #include @@ -1007,3 +1011,16 @@ JSLog *set_log_capture(const std::string &log_name) { void enable_logging() { RDKit::MinimalLib::LogHandle::enableLogging(); } void disable_logging() { RDKit::MinimalLib::LogHandle::disableLogging(); } + +#ifdef RDK_BUILD_MINIMAL_LIB_ZIP +JSMol * get_molzip(const JSMol &a, const JSMol &b, const std::string &details_json) { + + MolzipParams p = MolzipParams(); + if (!details_json.empty()) + parseMolzipParametersJSON(details_json.c_str(), &p); + + std::unique_ptr out = molzip(*(a.d_mol.get()), *(b.d_mol.get()), p); + + return new JSMol(new RDKit::RWMol(*(out).get())); +} +#endif diff --git a/Code/MinimalLib/minilib.h b/Code/MinimalLib/minilib.h index 7127888b58f..0cd6a6d4a9b 100644 --- a/Code/MinimalLib/minilib.h +++ b/Code/MinimalLib/minilib.h @@ -297,3 +297,7 @@ std::string get_mcs_as_json(const JSMolList &mols, const std::string &details_js std::string get_mcs_as_smarts(const JSMolList &mols, const std::string &details_json); JSMol *get_mcs_as_mol(const JSMolList &mols, const std::string &details_json); #endif + +#ifdef RDK_BUILD_MINIMAL_LIB_ZIP +JSMol * get_molzip(const JSMol &a, const JSMol &b, const std::string &details_json); +#endif diff --git a/Code/MinimalLib/tests/tests.js b/Code/MinimalLib/tests/tests.js index fc438d2b4e6..45df569d16b 100644 --- a/Code/MinimalLib/tests/tests.js +++ b/Code/MinimalLib/tests/tests.js @@ -1965,6 +1965,30 @@ function test_get_mmpa_frags() { } } +function test_link_frags() { + { + var mol1 = RDKitModule.get_mol("F/C=C/[*:1]"); + var mol2 = RDKitModule.get_mol("[*:1]F"); + var expectedLinkage = "F/C=C/F"; + var mol = RDKitModule.link(mol1, mol2); + assert(mol.get_smiles === expectedLinkage); + mol1.delete(); + mol2.delete(); + mol.delete(); + } + { + var mol1 = RDKitModule.get_mol("[C@H]([Xe])(F)([V])"); + var mol2 = RDKitModule.get_mol("[Xe]N.[V]I"); + var expectedLinkage = "N[C@@H](F)I"; + var details = JSON.stringify({ Label: 'AtomType', AtomSymbols: 'Xe,V' }); + var mol = RDKitModule.link(mol1, mol2, details); + assert(mol.get_smiles === expectedLinkage); + mol1.delete(); + mol2.delete(); + mol.delete(); + } +} + function test_hs_in_place() { { var mol = RDKitModule.get_mol("CC");