From c94a47bbd3ed74feeb6e050bd04822ba1cb22d07 Mon Sep 17 00:00:00 2001 From: Paolo Tosco Date: Tue, 29 Nov 2022 17:37:34 +0100 Subject: [PATCH] Enable get_molblock(details_json) from MinimalLib (#5806) * - enable get_molblock(details_json) from MinimalLib as it is already enabled in CFFI - enable useMolBlockWedging on get_molblock() in both CFFI and JS MinimalLib - add tests * - expose also addChiralHs Co-authored-by: Tosco, Paolo --- Code/MinimalLib/cffi_test.c | 68 ++++++++++++++++++++------------- Code/MinimalLib/cffiwrapper.cpp | 33 +++++----------- Code/MinimalLib/common.h | 25 ++++++++++++ Code/MinimalLib/jswrapper.cpp | 6 ++- Code/MinimalLib/minilib.cpp | 8 ++-- Code/MinimalLib/minilib.h | 10 ++++- Code/MinimalLib/tests/tests.js | 2 + 7 files changed, 95 insertions(+), 57 deletions(-) diff --git a/Code/MinimalLib/cffi_test.c b/Code/MinimalLib/cffi_test.c index 306a3d3fe..e8026435f 100644 --- a/Code/MinimalLib/cffi_test.c +++ b/Code/MinimalLib/cffi_test.c @@ -17,6 +17,31 @@ #endif #include +static const char molblock_native_wedging[] = "\n\ + MJ201100 \n\ +\n\ + 9 10 0 0 1 0 0 0 0 0999 V2000\n\ + 1.4885 -4.5513 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n\ + 2.0405 -3.9382 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ + 2.8610 -4.0244 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ + 3.1965 -3.2707 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ + 3.0250 -2.4637 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ + 2.2045 -2.3775 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ + 1.7920 -1.6630 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0\n\ + 1.8690 -3.1311 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ + 2.5834 -2.7186 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ + 2 1 1 1 0 0 0\n\ + 2 3 1 0 0 0 0\n\ + 4 3 1 0 0 0 0\n\ + 4 5 1 0 0 0 0\n\ + 6 5 1 0 0 0 0\n\ + 6 7 1 1 0 0 0\n\ + 6 8 1 0 0 0 0\n\ + 8 9 1 1 0 0 0\n\ + 8 2 1 0 0 0 0\n\ + 4 9 1 1 0 0 0\n\ +M END\n"; + void test_io() { char *pkl; size_t pkl_size; @@ -124,6 +149,22 @@ M END", free(molblock); molblock = NULL; + pkl2 = get_mol(molblock_native_wedging, &pkl2_size, ""); + assert(pkl2); + assert(pkl2_size > 0); + molblock = get_molblock(pkl2, pkl2_size, NULL); + assert(strstr(molblock, "4 3 1 6")); + assert(!strstr(molblock, "H ")); + free(molblock); + molblock = get_molblock(pkl2, pkl2_size, "{\"useMolBlockWedging\":true}"); + assert(!strstr(molblock, "4 3 1 6")); + assert(!strstr(molblock, "H ")); + free(molblock); + molblock = get_molblock(pkl2, pkl2_size, "{\"addChiralHs\":true}"); + assert(strstr(molblock, "H ")); + free(molblock); + free(pkl2); + molblock = get_v3kmolblock(pkl, pkl_size, NULL); pkl2 = get_mol(molblock, &pkl2_size, ""); assert(pkl2); @@ -237,32 +278,7 @@ void test_svg() { free(pkl); - pkl = get_mol( - "\n\ - MJ201100 \n\ -\n\ - 9 10 0 0 1 0 0 0 0 0999 V2000\n\ - 1.4885 -4.5513 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n\ - 2.0405 -3.9382 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ - 2.8610 -4.0244 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ - 3.1965 -3.2707 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ - 3.0250 -2.4637 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ - 2.2045 -2.3775 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ - 1.7920 -1.6630 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0\n\ - 1.8690 -3.1311 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ - 2.5834 -2.7186 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\ - 2 1 1 1 0 0 0\n\ - 2 3 1 0 0 0 0\n\ - 4 3 1 0 0 0 0\n\ - 4 5 1 0 0 0 0\n\ - 6 5 1 0 0 0 0\n\ - 6 7 1 1 0 0 0\n\ - 6 8 1 0 0 0 0\n\ - 8 9 1 1 0 0 0\n\ - 8 2 1 0 0 0 0\n\ - 4 9 1 1 0 0 0\n\ -M END\n", - &pkl_size, ""); + pkl = get_mol(molblock_native_wedging, &pkl_size, ""); assert(pkl); assert(pkl_size > 0); char *svg1 = get_svg(pkl, pkl_size, "{\"width\":350,\"height\":300}"); diff --git a/Code/MinimalLib/cffiwrapper.cpp b/Code/MinimalLib/cffiwrapper.cpp index 69c1f2185..f82abf0ee 100644 --- a/Code/MinimalLib/cffiwrapper.cpp +++ b/Code/MinimalLib/cffiwrapper.cpp @@ -153,27 +153,6 @@ std::string cxsmiles_helper(const char *pkl, size_t pkl_sz, auto data = MolToCXSmiles(mol, params); return data; } - -std::string molblock_helper(const char *pkl, size_t pkl_sz, - const char *details_json, bool forceV3000) { - if (!pkl || !pkl_sz) { - return ""; - } - auto mol = mol_from_pkl(pkl, pkl_sz); - bool includeStereo = true; - bool kekulize = true; - if (details_json && strlen(details_json)) { - boost::property_tree::ptree pt; - std::istringstream ss; - ss.str(details_json); - boost::property_tree::read_json(ss, pt); - PT_OPT_GET(includeStereo); - PT_OPT_GET(kekulize); - } - auto data = MolToMolBlock(mol, includeStereo, -1, kekulize, forceV3000); - return data; -} - } // namespace extern "C" char *get_smiles(const char *pkl, size_t pkl_sz, const char *details_json) { @@ -195,12 +174,20 @@ extern "C" char *get_cxsmiles(const char *pkl, size_t pkl_sz, } extern "C" char *get_molblock(const char *pkl, size_t pkl_sz, const char *details_json) { - auto data = molblock_helper(pkl, pkl_sz, details_json, false); + if (!pkl || !pkl_sz) { + return ""; + } + auto mol = mol_from_pkl(pkl, pkl_sz); + auto data = MinimalLib::molblock_helper(mol, details_json, false); return str_to_c(data); } extern "C" char *get_v3kmolblock(const char *pkl, size_t pkl_sz, const char *details_json) { - auto data = molblock_helper(pkl, pkl_sz, details_json, true); + if (!pkl || !pkl_sz) { + return ""; + } + auto mol = mol_from_pkl(pkl, pkl_sz); + auto data = MinimalLib::molblock_helper(mol, details_json, true); return str_to_c(data); } extern "C" char *get_json(const char *pkl, size_t pkl_sz, const char *) { diff --git a/Code/MinimalLib/common.h b/Code/MinimalLib/common.h index 8c60c2742..103c5f3eb 100644 --- a/Code/MinimalLib/common.h +++ b/Code/MinimalLib/common.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -448,6 +449,30 @@ std::string process_rxn_details( return ""; } +std::string molblock_helper(RWMol &mol, const char *details_json, bool forceV3000) { + bool includeStereo = true; + bool kekulize = true; + bool useMolBlockWedging = false; + bool addChiralHs = false; + if (details_json && strlen(details_json)) { + boost::property_tree::ptree pt; + std::istringstream ss; + ss.str(details_json); + boost::property_tree::read_json(ss, pt); + LPT_OPT_GET(includeStereo); + LPT_OPT_GET(kekulize); + LPT_OPT_GET(useMolBlockWedging); + LPT_OPT_GET(addChiralHs); + } + if (useMolBlockWedging) { + reapplyMolBlockWedging(mol); + } + if (addChiralHs) { + MolDraw2DUtils::prepareMolForDrawing(mol, false, true, false, false, false); + } + return MolToMolBlock(mol, includeStereo, -1, kekulize, forceV3000); +} + void get_sss_json(const ROMol &d_mol, const ROMol &q_mol, const MatchVectType &match, rj::Value &obj, rj::Document &doc) { diff --git a/Code/MinimalLib/jswrapper.cpp b/Code/MinimalLib/jswrapper.cpp index 3373e04f1..11594d6bd 100644 --- a/Code/MinimalLib/jswrapper.cpp +++ b/Code/MinimalLib/jswrapper.cpp @@ -335,8 +335,10 @@ EMSCRIPTEN_BINDINGS(RDKit_minimal) { .function("get_cxsmiles", &JSMol::get_cxsmiles) .function("get_smarts", &JSMol::get_smarts) .function("get_cxsmarts", &JSMol::get_cxsmarts) - .function("get_molblock", &JSMol::get_molblock) - .function("get_v3Kmolblock", &JSMol::get_v3Kmolblock) + .function("get_molblock", select_overload(&JSMol::get_molblock)) + .function("get_molblock", select_overload(&JSMol::get_molblock)) + .function("get_v3Kmolblock", select_overload(&JSMol::get_v3Kmolblock)) + .function("get_v3Kmolblock", select_overload(&JSMol::get_v3Kmolblock)) .function("get_as_uint8array", &get_as_uint8array) .function("get_inchi", &JSMol::get_inchi) .function("get_json", &JSMol::get_json) diff --git a/Code/MinimalLib/minilib.cpp b/Code/MinimalLib/minilib.cpp index 3ad21abe8..95ff5d1f4 100644 --- a/Code/MinimalLib/minilib.cpp +++ b/Code/MinimalLib/minilib.cpp @@ -121,17 +121,17 @@ std::string JSMol::get_inchi() const { ExtraInchiReturnValues rv; return MolToInchi(*d_mol, rv); } -std::string JSMol::get_molblock() const { +std::string JSMol::get_molblock(const std::string &details) const { if (!d_mol) { return ""; } - return MolToMolBlock(*d_mol); + return MinimalLib::molblock_helper(*d_mol, details.c_str(), false); } -std::string JSMol::get_v3Kmolblock() const { +std::string JSMol::get_v3Kmolblock(const std::string &details) const { if (!d_mol) { return ""; } - return MolToV3KMolBlock(*d_mol); + return MinimalLib::molblock_helper(*d_mol, details.c_str(), true); } std::string JSMol::get_json() const { if (!d_mol) { diff --git a/Code/MinimalLib/minilib.h b/Code/MinimalLib/minilib.h index 9f2e86460..dcd3cabe8 100644 --- a/Code/MinimalLib/minilib.h +++ b/Code/MinimalLib/minilib.h @@ -24,8 +24,14 @@ class JSMol { std::string get_cxsmiles() const; std::string get_smarts() const; std::string get_cxsmarts() const; - std::string get_molblock() const; - std::string get_v3Kmolblock() const; + std::string get_molblock(const std::string &details) const; + std::string get_molblock() const { + return get_molblock("{}"); + } + std::string get_v3Kmolblock(const std::string &details) const; + std::string get_v3Kmolblock() const { + return get_v3Kmolblock("{}"); + } std::string get_pickle() const; std::string get_inchi() const; std::string get_json() const; diff --git a/Code/MinimalLib/tests/tests.js b/Code/MinimalLib/tests/tests.js index 93d6be256..455874411 100644 --- a/Code/MinimalLib/tests/tests.js +++ b/Code/MinimalLib/tests/tests.js @@ -1060,6 +1060,8 @@ M END assert(svg2.includes("atom-8")); assert(!svg2.includes("atom-9")); assert(!svg2.includes("atom-10")); + assert(mol.get_molblock().includes("4 3 1 6")); + assert(!mol.get_molblock(JSON.stringify({ useMolBlockWedging: true })).includes("4 3 1 6")); } function test_get_frags() {