mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-03 21:44:30 +08:00
Optionally expose MCS to JS and extend optional compilation to JSReaction and JSSubstructLibrary (#6409)
* reverted all changes that did not really belong to this PR * I had forgotten ChemReactions_static * changes in response to review --------- Co-authored-by: Tosco, Paolo <paolo.tosco@novartis.com>
This commit is contained in:
@@ -66,6 +66,9 @@ option(RDK_BUILD_MINIMAL_LIB "build the minimal RDKit wrapper (for the JS bindin
|
||||
option(RDK_MINIMAL_LIB_SUPPORT_LEGACY_BROWSERS "build the minimal RDKit JS wrapper such that it supports legacy browsers" OFF)
|
||||
option(RDK_BUILD_CFFI_LIB "build the CFFI wrapper (for use in other programming languges)" OFF)
|
||||
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 )
|
||||
|
||||
set(RDK_BOOST_VERSION "1.58.0")
|
||||
|
||||
|
||||
@@ -24,6 +24,14 @@
|
||||
|
||||
namespace RDKit {
|
||||
|
||||
namespace {
|
||||
struct cmpCStr {
|
||||
bool operator()(const char *a, const char *b) const {
|
||||
return std::strcmp(a, b) < 0;
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
void MCSParameters::setMCSAtomTyperFromEnum(AtomComparator atomComp) {
|
||||
switch (atomComp) {
|
||||
case AtomCompareAny:
|
||||
@@ -45,7 +53,7 @@ void MCSParameters::setMCSAtomTyperFromEnum(AtomComparator atomComp) {
|
||||
|
||||
void MCSParameters::setMCSAtomTyperFromConstChar(const char* atomComp) {
|
||||
PRECONDITION(atomComp, "atomComp must not be NULL");
|
||||
static const std::map<const char*, AtomComparator> atomCompStringToEnum = {
|
||||
static const std::map<const char*, AtomComparator, cmpCStr> atomCompStringToEnum = {
|
||||
{"Any", AtomCompareAny},
|
||||
{"Elements", AtomCompareElements},
|
||||
{"Isotopes", AtomCompareIsotopes},
|
||||
@@ -75,7 +83,7 @@ void MCSParameters::setMCSBondTyperFromEnum(BondComparator bondComp) {
|
||||
|
||||
void MCSParameters::setMCSBondTyperFromConstChar(const char* bondComp) {
|
||||
PRECONDITION(bondComp, "bondComp must not be NULL");
|
||||
static const std::map<const char*, BondComparator> bondCompStringToEnum = {
|
||||
static const std::map<const char*, BondComparator, cmpCStr> bondCompStringToEnum = {
|
||||
{"Any", BondCompareAny},
|
||||
{"Order", BondCompareOrder},
|
||||
{"OrderExact", BondCompareOrderExact}};
|
||||
|
||||
@@ -1043,6 +1043,8 @@ void testJSONParameters() {
|
||||
", \"MatchFusedRings\": true"
|
||||
", \"MatchFusedRingsStrict\": true"
|
||||
", \"InitialSeed\": \"CNC\""
|
||||
", \"AtomCompare\": \"Isotopes\""
|
||||
", \"BondCompare\": \"OrderExact\""
|
||||
"}";
|
||||
parseMCSParametersJSON(json, &pj);
|
||||
TEST_ASSERT(!pj.MaximizeBonds && pj.Threshold == 0.7 && pj.Timeout == 3 &&
|
||||
@@ -1055,6 +1057,8 @@ void testJSONParameters() {
|
||||
pj.BondCompareParameters.CompleteRingsOnly &&
|
||||
pj.BondCompareParameters.MatchFusedRings &&
|
||||
pj.BondCompareParameters.MatchFusedRingsStrict &&
|
||||
pj.AtomTyper == MCSAtomCompareIsotopes &&
|
||||
pj.BondTyper == MCSBondCompareOrderExact &&
|
||||
0 == strcmp(pj.InitialSeed.c_str(), "CNC"));
|
||||
}
|
||||
{
|
||||
|
||||
@@ -2,6 +2,22 @@ include_directories(${RDKit_ExternalDir})
|
||||
include_directories(${RDKit_ExternalDir}/rapidjson-1.1.0/include)
|
||||
|
||||
if(RDK_BUILD_MINIMAL_LIB)
|
||||
set(MINIMAL_LIB_LIBRARIES "MolInterchange_static;Abbreviations_static;"
|
||||
"CIPLabeler_static;MolDraw2D_static;Depictor_static;RDInchiLib_static;"
|
||||
"SubstructMatch_static;FileParsers_static;"
|
||||
"SmilesParse_static;GraphMol_static;RDGeometryLib_static;RDGeneral_static")
|
||||
if(RDK_BUILD_MINIMAL_LIB_RXN)
|
||||
add_definitions(-DRDK_BUILD_MINIMAL_LIB_RXN)
|
||||
set(MINIMAL_LIB_LIBRARIES "${MINIMAL_LIB_LIBRARIES};ChemReactions_static")
|
||||
endif()
|
||||
if(RDK_BUILD_MINIMAL_LIB_SUBSTRUCTLIBRARY)
|
||||
add_definitions(-DRDK_BUILD_MINIMAL_LIB_SUBSTRUCTLIBRARY)
|
||||
set(MINIMAL_LIB_LIBRARIES "${MINIMAL_LIB_LIBRARIES};SubstructLibrary_static")
|
||||
endif()
|
||||
if(RDK_BUILD_MINIMAL_LIB_MCS)
|
||||
add_definitions(-DRDK_BUILD_MINIMAL_LIB_MCS)
|
||||
set(MINIMAL_LIB_LIBRARIES "${MINIMAL_LIB_LIBRARIES};FMCS_static")
|
||||
endif()
|
||||
if(RDK_BUILD_FREETYPE_SUPPORT)
|
||||
if( ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
set(USE_FLAGS "-s USE_FREETYPE=1")
|
||||
@@ -10,10 +26,7 @@ if(RDK_BUILD_MINIMAL_LIB)
|
||||
endif()
|
||||
endif()
|
||||
add_executable(RDKit_minimal jswrapper.cpp minilib.cpp)
|
||||
target_link_libraries(RDKit_minimal MolInterchange_static Abbreviations_static
|
||||
CIPLabeler_static MolDraw2D_static Depictor_static RDInchiLib_static
|
||||
SubstructMatch_static SubstructLibrary_static FileParsers_static
|
||||
SmilesParse_static GraphMol_static RDGeometryLib_static RDGeneral_static)
|
||||
target_link_libraries(RDKit_minimal ${MINIMAL_LIB_LIBRARIES})
|
||||
|
||||
set_target_properties(RDKit_minimal PROPERTIES LINK_FLAGS "--bind")
|
||||
endif(RDK_BUILD_MINIMAL_LIB)
|
||||
|
||||
@@ -107,6 +107,7 @@ std::string draw_to_canvas_with_highlights(JSMol &self, emscripten::val canvas,
|
||||
return "";
|
||||
}
|
||||
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_RXN
|
||||
std::string draw_rxn_to_canvas_with_offset(JSReaction &self,
|
||||
emscripten::val canvas, int offsetx,
|
||||
int offsety, int width, int height) {
|
||||
@@ -172,11 +173,22 @@ std::string draw_rxn_to_canvas_with_highlights(JSReaction &self,
|
||||
: &highlightColorsReactants);
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
|
||||
JSMol *get_mol_no_details(const std::string &input) {
|
||||
return get_mol(input, std::string());
|
||||
}
|
||||
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_MCS
|
||||
JSMol *get_mcs_as_mol_no_details(const JSMolList &mols) {
|
||||
return get_mcs_as_mol(mols, std::string());
|
||||
}
|
||||
|
||||
std::string get_mcs_as_smarts_no_details(const JSMolList &mols) {
|
||||
return get_mcs_as_smarts(mols, std::string());
|
||||
}
|
||||
#endif
|
||||
|
||||
emscripten::val binary_string_to_uint8array(const std::string &pkl) {
|
||||
emscripten::val view(emscripten::typed_memory_view(
|
||||
pkl.size(), reinterpret_cast<const unsigned char *>(pkl.c_str())));
|
||||
@@ -204,9 +216,11 @@ JSMol *get_mol_from_uint8array(const emscripten::val &pklAsUInt8Array) {
|
||||
return get_mol_from_pickle(pklAsUInt8Array.as<std::string>());
|
||||
}
|
||||
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_RXN
|
||||
JSReaction *get_rxn_no_details(const std::string &input) {
|
||||
return get_rxn(input, std::string());
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string generate_aligned_coords_helper(JSMol &self,
|
||||
const JSMol &templateMol,
|
||||
@@ -312,7 +326,7 @@ emscripten::val get_frags_helper(JSMol &self, const std::string &details) {
|
||||
auto res = self.get_frags(details);
|
||||
auto obj = emscripten::val::object();
|
||||
auto molArray = emscripten::val::object();
|
||||
obj.set("molIterator", res.first);
|
||||
obj.set("molList", res.first);
|
||||
obj.set("mappings", res.second);
|
||||
return obj;
|
||||
}
|
||||
@@ -321,6 +335,7 @@ emscripten::val get_frags_helper(JSMol &self) {
|
||||
return get_frags_helper(self, "{}");
|
||||
}
|
||||
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_SUBSTRUCTLIBRARY
|
||||
int add_trusted_smiles_and_pattern_fp_helper(
|
||||
JSSubstructLibrary &self, const std::string &smi,
|
||||
const emscripten::val &patternFpAsUInt8Array) {
|
||||
@@ -355,6 +370,7 @@ emscripten::val get_matches_as_uint32array(const JSSubstructLibrary &self,
|
||||
self.d_defaultNumThreads,
|
||||
self.d_defaultMaxResults);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RDK_BUILD_AVALON_SUPPORT
|
||||
emscripten::val get_avalon_fp_as_uint8array(const JSMol &self,
|
||||
@@ -555,14 +571,26 @@ EMSCRIPTEN_BINDINGS(RDKit_minimal) {
|
||||
.function("straighten_depiction",
|
||||
select_overload<void()>(&JSMol::straighten_depiction))
|
||||
.function("straighten_depiction",
|
||||
select_overload<void(bool)>(&JSMol::straighten_depiction));
|
||||
select_overload<void(bool)>(&JSMol::straighten_depiction))
|
||||
.function("get_num_atoms", select_overload<unsigned int(bool) const>(
|
||||
&JSMol::get_num_atoms))
|
||||
.function("get_num_atoms",
|
||||
select_overload<unsigned int() const>(&JSMol::get_num_atoms))
|
||||
.function("get_num_bonds", &JSMol::get_num_bonds)
|
||||
;
|
||||
|
||||
class_<JSMolIterator>("MolIterator")
|
||||
.function("next", &JSMolIterator::next, allow_raw_pointers())
|
||||
.function("reset", &JSMolIterator::reset)
|
||||
.function("at_end", &JSMolIterator::at_end)
|
||||
.function("size", &JSMolIterator::size);
|
||||
class_<JSMolList>("MolList")
|
||||
.constructor<>()
|
||||
.function("append", &JSMolList::append)
|
||||
.function("insert", &JSMolList::insert)
|
||||
.function("at", &JSMolList::at, allow_raw_pointers())
|
||||
.function("pop", &JSMolList::pop, allow_raw_pointers())
|
||||
.function("next", &JSMolList::next, allow_raw_pointers())
|
||||
.function("reset", &JSMolList::reset)
|
||||
.function("at_end", &JSMolList::at_end)
|
||||
.function("size", &JSMolList::size);
|
||||
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_RXN
|
||||
class_<JSReaction>("Reaction")
|
||||
#ifdef __EMSCRIPTEN__
|
||||
.function("draw_to_canvas_with_offset", &draw_rxn_to_canvas_with_offset)
|
||||
@@ -577,7 +605,9 @@ EMSCRIPTEN_BINDINGS(RDKit_minimal) {
|
||||
|
||||
.function("get_svg_with_highlights",
|
||||
&JSReaction::get_svg_with_highlights);
|
||||
#endif
|
||||
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_SUBSTRUCTLIBRARY
|
||||
class_<JSSubstructLibrary>("SubstructLibrary")
|
||||
.constructor<>()
|
||||
.constructor<unsigned int>()
|
||||
@@ -627,7 +657,9 @@ EMSCRIPTEN_BINDINGS(RDKit_minimal) {
|
||||
.function("count_matches",
|
||||
select_overload<unsigned int(const JSMol &) const>(
|
||||
&JSSubstructLibrary::count_matches))
|
||||
.function("size", &JSSubstructLibrary::size);
|
||||
.function("size", &JSSubstructLibrary::size)
|
||||
#endif
|
||||
;
|
||||
|
||||
function("version", &version);
|
||||
function("prefer_coordgen", &prefer_coordgen);
|
||||
@@ -640,6 +672,14 @@ EMSCRIPTEN_BINDINGS(RDKit_minimal) {
|
||||
allow_raw_pointers());
|
||||
function("get_mol_copy", &get_mol_copy, allow_raw_pointers());
|
||||
function("get_qmol", &get_qmol, allow_raw_pointers());
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_RXN
|
||||
function("get_rxn", &get_rxn, allow_raw_pointers());
|
||||
function("get_rxn", &get_rxn_no_details, allow_raw_pointers());
|
||||
#endif
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_MCS
|
||||
function("get_mcs_as_mol", &get_mcs_as_mol, allow_raw_pointers());
|
||||
function("get_mcs_as_mol", &get_mcs_as_mol_no_details, allow_raw_pointers());
|
||||
function("get_mcs_as_smarts", &get_mcs_as_smarts);
|
||||
function("get_mcs_as_smarts", &get_mcs_as_smarts_no_details);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -24,7 +24,12 @@
|
||||
#include <GraphMol/MolDraw2D/MolDraw2DSVG.h>
|
||||
#include <GraphMol/MolDraw2D/MolDraw2DUtils.h>
|
||||
#include <GraphMol/Substruct/SubstructMatch.h>
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_SUBSTRUCTLIBRARY
|
||||
#include <GraphMol/SubstructLibrary/SubstructLibrary.h>
|
||||
#endif
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_MCS
|
||||
#include <GraphMol/FMCS/FMCS.h>
|
||||
#endif
|
||||
#include <GraphMol/Descriptors/Property.h>
|
||||
#include <GraphMol/Descriptors/MolDescriptors.h>
|
||||
#include <GraphMol/MolInterchange/MolInterchange.h>
|
||||
@@ -625,7 +630,7 @@ void JSMol::straighten_depiction(bool minimizeRotation) {
|
||||
RDDepict::straightenDepiction(*d_mol, -1, minimizeRotation);
|
||||
}
|
||||
|
||||
std::pair<JSMolIterator *, std::string> JSMol::get_frags(
|
||||
std::pair<JSMolList *, std::string> JSMol::get_frags(
|
||||
const std::string &details_json) {
|
||||
if (!d_mol) {
|
||||
return std::make_pair(nullptr, "");
|
||||
@@ -639,10 +644,21 @@ std::pair<JSMolIterator *, std::string> JSMol::get_frags(
|
||||
auto molFrags = MolOps::getMolFrags(*d_mol, sanitizeFrags, &frags,
|
||||
&fragsMolAtomMapping, copyConformers);
|
||||
return std::make_pair(
|
||||
new JSMolIterator(molFrags),
|
||||
new JSMolList(molFrags),
|
||||
MinimalLib::get_mol_frags_mappings(frags, fragsMolAtomMapping));
|
||||
}
|
||||
|
||||
unsigned int JSMol::get_num_atoms(bool heavyOnly) const {
|
||||
assert(d_mol);
|
||||
return heavyOnly ? d_mol->getNumHeavyAtoms() : d_mol->getNumAtoms();
|
||||
}
|
||||
|
||||
unsigned int JSMol::get_num_bonds() const {
|
||||
assert(d_mol);
|
||||
return d_mol->getNumBonds();
|
||||
}
|
||||
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_RXN
|
||||
std::string JSReaction::get_svg(int w, int h) const {
|
||||
if (!d_rxn) {
|
||||
return "";
|
||||
@@ -659,7 +675,46 @@ std::string JSReaction::get_svg_with_highlights(
|
||||
int h = d_defaultHeight;
|
||||
return MinimalLib::rxn_to_svg(*d_rxn, w, h, details);
|
||||
}
|
||||
#endif
|
||||
|
||||
JSMol *JSMolList::next() {
|
||||
return (d_idx < d_mols.size()
|
||||
? new JSMol(new RDKit::RWMol(*d_mols.at(d_idx++)))
|
||||
: nullptr);
|
||||
}
|
||||
|
||||
JSMol *JSMolList::at(size_t idx) const {
|
||||
return (idx < d_mols.size() ? new JSMol(new RDKit::RWMol(*d_mols.at(idx)))
|
||||
: nullptr);
|
||||
}
|
||||
|
||||
JSMol *JSMolList::pop(size_t idx) {
|
||||
JSMol *res = nullptr;
|
||||
if (idx < d_mols.size()) {
|
||||
res = new JSMol(new RDKit::RWMol(*d_mols.at(idx)));
|
||||
d_mols.erase(d_mols.begin() + idx);
|
||||
if (d_idx > idx) {
|
||||
--d_idx;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
size_t JSMolList::append(const JSMol &mol) {
|
||||
d_mols.emplace_back(new ROMol(*mol.d_mol));
|
||||
return d_mols.size();
|
||||
}
|
||||
|
||||
size_t JSMolList::insert(size_t idx, const JSMol &mol) {
|
||||
size_t res = 0;
|
||||
if (idx < d_mols.size()) {
|
||||
d_mols.emplace(d_mols.begin() + idx, new ROMol(*mol.d_mol));
|
||||
res = d_mols.size();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_SUBSTRUCTLIBRARY
|
||||
JSSubstructLibrary::JSSubstructLibrary(unsigned int num_bits) :
|
||||
d_fpHolder(nullptr) {
|
||||
boost::shared_ptr<CachedTrustedSmilesMolHolder> molHolderSptr(new CachedTrustedSmilesMolHolder());
|
||||
@@ -771,6 +826,7 @@ unsigned int JSSubstructLibrary::count_matches(const JSMol &q,
|
||||
false, numThreads)
|
||||
: 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string get_inchikey_for_inchi(const std::string &input) {
|
||||
return InchiToInchiKey(input);
|
||||
@@ -805,10 +861,12 @@ JSMol *get_qmol(const std::string &input) {
|
||||
return new JSMol(mol);
|
||||
}
|
||||
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_RXN
|
||||
JSReaction *get_rxn(const std::string &input, const std::string &details_json) {
|
||||
auto rxn = MinimalLib::rxn_from_input(input, details_json);
|
||||
return new JSReaction(rxn);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string version() { return std::string(rdkitVersion); }
|
||||
|
||||
@@ -829,3 +887,28 @@ bool allow_non_tetrahedral_chirality(bool value) {
|
||||
Chirality::setAllowNontetrahedralChirality(value);
|
||||
return was;
|
||||
}
|
||||
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_MCS
|
||||
namespace {
|
||||
MCSResult getMcsResult(const JSMolList &molList,
|
||||
const std::string &details_json) {
|
||||
MCSParameters p;
|
||||
if (!details_json.empty()) {
|
||||
parseMCSParametersJSON(details_json.c_str(), &p);
|
||||
}
|
||||
return RDKit::findMCS(molList.mols(), &p);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::string get_mcs_as_smarts(const JSMolList &molList,
|
||||
const std::string &details_json) {
|
||||
auto res = getMcsResult(molList, details_json);
|
||||
return res.SmartsString;
|
||||
}
|
||||
|
||||
JSMol *get_mcs_as_mol(const JSMolList &molList,
|
||||
const std::string &details_json) {
|
||||
auto res = getMcsResult(molList, details_json);
|
||||
return new JSMol(new RWMol(*res.QueryMol));
|
||||
}
|
||||
#endif
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <GraphMol/ChemReactions/Reaction.h>
|
||||
#include <GraphMol/ChemReactions/ReactionParser.h>
|
||||
|
||||
class JSMolIterator;
|
||||
class JSMolList;
|
||||
|
||||
class JSMol {
|
||||
public:
|
||||
@@ -132,35 +132,41 @@ class JSMol {
|
||||
double normalize_depiction() { return normalize_depiction(1, -1.); }
|
||||
void straighten_depiction(bool minimizeRotation);
|
||||
void straighten_depiction() { straighten_depiction(false); }
|
||||
std::pair<JSMolIterator *, std::string> get_frags(
|
||||
std::pair<JSMolList *, std::string> get_frags(
|
||||
const std::string &details_json);
|
||||
std::pair<JSMolIterator *, std::string> get_frags() {
|
||||
std::pair<JSMolList *, std::string> get_frags() {
|
||||
return get_frags("{}");
|
||||
}
|
||||
unsigned int get_num_atoms(bool heavyOnly) const;
|
||||
unsigned int get_num_atoms() const { return get_num_atoms(false); };
|
||||
unsigned int get_num_bonds() const;
|
||||
|
||||
std::unique_ptr<RDKit::RWMol> d_mol;
|
||||
static constexpr int d_defaultWidth = 250;
|
||||
static constexpr int d_defaultHeight = 200;
|
||||
};
|
||||
|
||||
class JSMolIterator {
|
||||
class JSMolList {
|
||||
public:
|
||||
JSMolIterator(const std::vector<RDKit::ROMOL_SPTR> &mols)
|
||||
JSMolList(const std::vector<RDKit::ROMOL_SPTR> &mols)
|
||||
: d_mols(mols), d_idx(0){};
|
||||
JSMol *next() {
|
||||
return (d_idx < d_mols.size()
|
||||
? new JSMol(new RDKit::RWMol(*d_mols.at(d_idx++)))
|
||||
: nullptr);
|
||||
}
|
||||
JSMolList() : d_idx(0){};
|
||||
JSMol *next();
|
||||
size_t append(const JSMol &mol);
|
||||
size_t insert(size_t idx, const JSMol &mol);
|
||||
JSMol *at(size_t idx) const;
|
||||
JSMol *pop(size_t idx);
|
||||
void reset() { d_idx = 0; }
|
||||
bool at_end() { return d_idx == d_mols.size(); }
|
||||
size_t size() { return d_mols.size(); }
|
||||
bool at_end() const { return d_idx == d_mols.size(); }
|
||||
size_t size() const { return d_mols.size(); }
|
||||
const std::vector<RDKit::ROMOL_SPTR> &mols() const { return d_mols; }
|
||||
|
||||
private:
|
||||
std::vector<RDKit::ROMOL_SPTR> d_mols;
|
||||
size_t d_idx;
|
||||
};
|
||||
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_RXN
|
||||
class JSReaction {
|
||||
public:
|
||||
JSReaction() : d_rxn(nullptr) {}
|
||||
@@ -177,7 +183,9 @@ class JSReaction {
|
||||
static constexpr int d_defaultWidth = 800;
|
||||
static constexpr int d_defaultHeight = 200;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_SUBSTRUCTLIBRARY
|
||||
class JSSubstructLibrary {
|
||||
public:
|
||||
JSSubstructLibrary(unsigned int num_bits);
|
||||
@@ -222,14 +230,21 @@ class JSSubstructLibrary {
|
||||
private:
|
||||
inline int add_mol_helper(const RDKit::ROMol &mol);
|
||||
};
|
||||
#endif
|
||||
|
||||
std::string get_inchikey_for_inchi(const std::string &input);
|
||||
JSMol *get_mol(const std::string &input, const std::string &details_json);
|
||||
JSMol *get_mol_from_pickle(const std::string &pkl);
|
||||
JSMol *get_mol_copy(const JSMol &other);
|
||||
JSMol *get_qmol(const std::string &input);
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_RXN
|
||||
JSReaction *get_rxn(const std::string &input, const std::string &details_json);
|
||||
#endif
|
||||
std::string version();
|
||||
void prefer_coordgen(bool prefer);
|
||||
bool use_legacy_stereo_perception(bool value);
|
||||
bool allow_non_tetrahedral_chirality(bool value);
|
||||
#ifdef RDK_BUILD_MINIMAL_LIB_MCS
|
||||
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
|
||||
|
||||
@@ -1769,17 +1769,17 @@ function test_get_frags() {
|
||||
frags: [0,0,0,0,0,0,1,1,1,1,2,2,2,2,2],
|
||||
fragsMolAtomMapping: [[0,1,2,3,4,5],[6,7,8,9],[10,11,12,13,14]],
|
||||
};
|
||||
var { molIterator, mappings } = mol.get_frags();
|
||||
assert(molIterator.size() === 3);
|
||||
var { molList, mappings } = mol.get_frags();
|
||||
assert(molList.size() === 3);
|
||||
assert(JSON.stringify(JSON.parse(mappings)) === JSON.stringify(expectedMappings));
|
||||
var i = 0;
|
||||
while (!molIterator.at_end()) {
|
||||
var mol = molIterator.next();
|
||||
while (!molList.at_end()) {
|
||||
var mol = molList.next();
|
||||
assert(mol.get_smiles() === expectedFragSmiles[i++]);
|
||||
mol.delete();
|
||||
}
|
||||
assert(!molIterator.next());
|
||||
molIterator.delete();
|
||||
assert(!molList.next());
|
||||
molList.delete();
|
||||
}
|
||||
{
|
||||
var mol = RDKitModule.get_mol("N(C)(C)(C)C.c1ccc1", JSON.stringify({sanitize: false}));
|
||||
@@ -1790,16 +1790,16 @@ function test_get_frags() {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
assert(exceptionThrown);
|
||||
var { molIterator, mappings } = mol.get_frags(JSON.stringify({sanitizeFrags: false}));
|
||||
assert(molIterator.size() === 2);
|
||||
var { molList, mappings } = mol.get_frags(JSON.stringify({sanitizeFrags: false}));
|
||||
assert(molList.size() === 2);
|
||||
var i = 0;
|
||||
while (!molIterator.at_end()) {
|
||||
var mol = molIterator.next();
|
||||
while (!molList.at_end()) {
|
||||
var mol = molList.next();
|
||||
assert(mol.get_smiles() === expectedFragSmilesNonSanitized[i++]);
|
||||
mol.delete();
|
||||
}
|
||||
assert(!molIterator.next());
|
||||
molIterator.delete();
|
||||
assert(!molList.next());
|
||||
molList.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2045,6 +2045,270 @@ M END`);
|
||||
}
|
||||
}
|
||||
|
||||
function molIteratorFromSmiArray(smiArray) {
|
||||
const molList = new RDKitModule.MolList();
|
||||
assert(molList);
|
||||
smiArray.forEach((smiName) => {
|
||||
const [smi, name] = smiName.split(' ');
|
||||
let mol;
|
||||
try {
|
||||
mol = RDKitModule.get_mol(smi);
|
||||
assert(mol);
|
||||
molList.append(mol);
|
||||
} finally {
|
||||
if (mol) {
|
||||
mol.delete();
|
||||
}
|
||||
}
|
||||
});
|
||||
return molList;
|
||||
}
|
||||
|
||||
function test_mol_iterator() {
|
||||
const smiArray = [ 'C1CC1', 'C1CCCC1' ];
|
||||
let molList;
|
||||
let mol;
|
||||
try {
|
||||
molList = molIteratorFromSmiArray(smiArray);
|
||||
assert(molList);
|
||||
assert.equal(molList.size(), 2);
|
||||
assert(!molList.at_end());
|
||||
try {
|
||||
mol = molList.next();
|
||||
assert(mol);
|
||||
} finally {
|
||||
if (mol) {
|
||||
mol.delete();
|
||||
}
|
||||
}
|
||||
try {
|
||||
mol = molList.next();
|
||||
assert(mol);
|
||||
} finally {
|
||||
if (mol) {
|
||||
mol.delete();
|
||||
}
|
||||
}
|
||||
mol = molList.next();
|
||||
assert(!mol);
|
||||
assert(molList.at_end());
|
||||
try {
|
||||
mol = molList.at(0);
|
||||
assert.equal(mol.get_num_atoms(), 3);
|
||||
} finally {
|
||||
if (mol) {
|
||||
mol.delete();
|
||||
}
|
||||
}
|
||||
try {
|
||||
mol = molList.at(1);
|
||||
assert.equal(mol.get_num_atoms(), 5);
|
||||
} finally {
|
||||
if (mol) {
|
||||
mol.delete();
|
||||
}
|
||||
}
|
||||
assert(molList.at_end());
|
||||
try {
|
||||
mol = RDKitModule.get_mol('C1CCC1');
|
||||
assert(mol);
|
||||
molList.insert(1, mol);
|
||||
assert.equal(molList.size(), 3);
|
||||
assert(!molList.at_end());
|
||||
} finally {
|
||||
if (mol) {
|
||||
mol.delete();
|
||||
}
|
||||
}
|
||||
molList.reset();
|
||||
assert(!molList.at_end());
|
||||
try {
|
||||
mol = molList.at(1);
|
||||
assert.equal(mol.get_num_atoms(), 4);
|
||||
} finally {
|
||||
if (mol) {
|
||||
mol.delete();
|
||||
}
|
||||
}
|
||||
try {
|
||||
mol = molList.pop(0);
|
||||
assert.equal(mol.get_num_atoms(), 3);
|
||||
} finally {
|
||||
if (mol) {
|
||||
mol.delete();
|
||||
}
|
||||
}
|
||||
assert.equal(molList.size(), 2);
|
||||
let i = 0;
|
||||
while (!molList.at_end()) {
|
||||
try {
|
||||
mol = molList.next();
|
||||
} finally {
|
||||
if (mol) {
|
||||
++i;
|
||||
mol.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
assert.equal(i, 2);
|
||||
assert(molList.at_end());
|
||||
try {
|
||||
mol = molList.pop(0);
|
||||
assert.equal(mol.get_num_atoms(), 4);
|
||||
} finally {
|
||||
if (mol) {
|
||||
mol.delete();
|
||||
}
|
||||
}
|
||||
assert.equal(molList.size(), 1);
|
||||
assert(molList.at_end());
|
||||
try {
|
||||
mol = molList.pop(0);
|
||||
assert.equal(mol.get_num_atoms(), 5);
|
||||
} finally {
|
||||
if (mol) {
|
||||
mol.delete();
|
||||
}
|
||||
}
|
||||
assert.equal(molList.size(), 0);
|
||||
assert(molList.at_end());
|
||||
assert(!molList.pop(0));
|
||||
try {
|
||||
mol = RDKitModule.get_mol('C1CCCCC1');
|
||||
assert(mol);
|
||||
molList.append(mol);
|
||||
assert.equal(molList.size(), 1);
|
||||
assert(!molList.at_end());
|
||||
} finally {
|
||||
if (mol) {
|
||||
mol.delete();
|
||||
}
|
||||
}
|
||||
assert(!molList.at(1));
|
||||
try {
|
||||
mol = molList.at(0);
|
||||
assert(mol);
|
||||
assert(mol.get_num_atoms(), 6);
|
||||
} finally {
|
||||
if (mol) {
|
||||
mol.delete();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (molList) {
|
||||
molList.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function test_mcs() {
|
||||
{
|
||||
const smiArray = [
|
||||
"COc1cc2nc(-c3cc(NC(=O)CSc4ccc(Cl)cc4)ccc3)oc2cc1 CHEMBL1479679",
|
||||
"COc1cc2nc(-c3cc(NC(=O)CSc4ccc(Cl)cc4)c(C)cc3)oc2cc1 CHEMBL1333382",
|
||||
"Cc1cc2oc(-c3cc(NC(=O)CSc4ccc(Cl)cc4)ccc3)nc2cc1 CHEMBL1437584",
|
||||
"COc1c(NC(=O)CSc2ccc(Cl)cc2)cc(-c2nc3ccccc3o2)cc1 CHEMBL1601350",
|
||||
"Cc1cc2nc(-c3cccc(NC(=O)CSc4ccc(Cl)cc4)c3)oc2cc1C CHEMBL1398008",
|
||||
"Cc1cc2oc(-c3cc(NC(=O)CSc4ccc(Cl)cc4)c(C)cc3)nc2cc1 CHEMBL1612903",
|
||||
"COc1cc2nc(-c3cc(NC(=O)Cc4ccc(Cl)cc4)c(C)cc3)oc2cc1 CHEMBL1316483",
|
||||
"Cc1c(NC(=O)CSc2ccc(Cl)cc2)cccc1-c1nc2cc(Cl)ccc2o1 CHEMBL1568754",
|
||||
"COc1ccc2oc(-c3ccc(C)c(NC(=O)COc4cc(C)cc(C)c4)c3)nc2c1 CHEMBL1436972",
|
||||
"Cc1ccc(SCC(=O)Nc2cc(-c3nc4cc(C)ccc4o3)c(O)cc2)cc1 CHEMBL1611932",
|
||||
];
|
||||
let molList;
|
||||
let mcsSmarts;
|
||||
try {
|
||||
molList = molIteratorFromSmiArray(smiArray);
|
||||
let mcsMol;
|
||||
try {
|
||||
mcsMol = RDKitModule.get_mcs_as_mol(molList);
|
||||
assert(mcsMol);
|
||||
assert.equal(mcsMol.get_smarts(), '[#6]1:[#6]:[#6]2:[#8]:[#6](:[#7]:[#6]:2:[#6]:[#6]:1)-[#6]1:[#6]:[#6](-[#7]-[#6](=[#8])-[#6]):[#6]:[#6]:[#6]:1');
|
||||
mcsSmarts = RDKitModule.get_mcs_as_smarts(molList);
|
||||
} finally {
|
||||
if (mcsMol) {
|
||||
mcsMol.delete();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (molList) {
|
||||
molList.delete();
|
||||
}
|
||||
}
|
||||
assert(mcsSmarts);
|
||||
assert.equal(mcsSmarts, '[#6]1:[#6]:[#6]2:[#8]:[#6](:[#7]:[#6]:2:[#6]:[#6]:1)-[#6]1:[#6]:[#6](-[#7]-[#6](=[#8])-[#6]):[#6]:[#6]:[#6]:1');
|
||||
}
|
||||
{
|
||||
const smiArray = ["C1CC1N2CC2", "C1CC1N"];
|
||||
let molList;
|
||||
try {
|
||||
molList = molIteratorFromSmiArray(smiArray);
|
||||
let mcsMol;
|
||||
try {
|
||||
mcsMol = RDKitModule.get_mcs_as_mol(molList);
|
||||
assert(mcsMol);
|
||||
assert.equal(mcsMol.get_num_atoms(), 4);
|
||||
assert.equal(mcsMol.get_num_bonds(), 4);
|
||||
} finally {
|
||||
if (mcsMol) {
|
||||
mcsMol.delete();
|
||||
}
|
||||
}
|
||||
try {
|
||||
mcsMol = RDKitModule.get_mcs_as_mol(molList, JSON.stringify({ RingMatchesRingOnly: true }));
|
||||
assert(mcsMol);
|
||||
assert.equal(mcsMol.get_num_atoms(), 3);
|
||||
assert.equal(mcsMol.get_num_bonds(), 3);
|
||||
} finally {
|
||||
if (mcsMol) {
|
||||
mcsMol.delete();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (molList) {
|
||||
molList.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
const smiArray = ["NC1CCCCC1", "Cc1ccccc1", "Cc1cnccc1", "CC1CCCCN1"];
|
||||
let molList;
|
||||
const res = new Set();
|
||||
try {
|
||||
molList = molIteratorFromSmiArray(smiArray);
|
||||
["Elements", "Any"].forEach((AtomCompare) => {
|
||||
["Order", "OrderExact"].forEach((BondCompare) => {
|
||||
const details = {
|
||||
AtomCompare,
|
||||
BondCompare
|
||||
};
|
||||
let mcsSmarts;
|
||||
mcsSmarts = RDKitModule.get_mcs_as_smarts(molList, JSON.stringify(details));
|
||||
assert(mcsSmarts);
|
||||
res.add(mcsSmarts);
|
||||
});
|
||||
});
|
||||
} finally {
|
||||
if (molList) {
|
||||
molList.delete();
|
||||
}
|
||||
}
|
||||
assert(res.size === 4);
|
||||
}
|
||||
}
|
||||
|
||||
function test_get_num_atoms_bonds() {
|
||||
var mol = RDKitModule.get_mol('CCCC');
|
||||
var molH = RDKitModule.get_mol_copy(mol);
|
||||
molH.add_hs_in_place();
|
||||
assert.equal(mol.get_num_atoms(), molH.get_num_atoms(true));
|
||||
assert.equal(mol.get_num_atoms(), 4);
|
||||
assert.equal(molH.get_num_atoms(), 14);
|
||||
assert.equal(molH.get_num_atoms(false), 14);
|
||||
assert.equal(mol.get_num_bonds(), 3);
|
||||
assert.equal(molH.get_num_bonds(), 13);
|
||||
}
|
||||
|
||||
initRDKitModule().then(function(instance) {
|
||||
var done = {};
|
||||
const waitAllTestsFinished = () => {
|
||||
@@ -2066,11 +2330,13 @@ initRDKitModule().then(function(instance) {
|
||||
test_sketcher_services();
|
||||
test_sketcher_services2();
|
||||
test_abbreviations();
|
||||
test_substruct_library(done);
|
||||
test_substruct_library_merge_hs();
|
||||
test_substruct_library_empty_mols();
|
||||
test_substruct_library_empty_lib();
|
||||
test_substruct_library_empty_query();
|
||||
if (RDKitModule.SubstructLibrary) {
|
||||
test_substruct_library(done);
|
||||
test_substruct_library_merge_hs();
|
||||
test_substruct_library_empty_mols();
|
||||
test_substruct_library_empty_lib();
|
||||
test_substruct_library_empty_query();
|
||||
}
|
||||
test_generate_aligned_coords();
|
||||
test_isotope_labels();
|
||||
test_generate_aligned_coords_allow_rgroups();
|
||||
@@ -2086,7 +2352,9 @@ initRDKitModule().then(function(instance) {
|
||||
test_normalize_depiction();
|
||||
test_straighten_depiction();
|
||||
test_flexicanvas();
|
||||
test_rxn_drawing();
|
||||
if (RDKitModule.get_rxn) {
|
||||
test_rxn_drawing();
|
||||
}
|
||||
test_legacy_stereochem();
|
||||
test_allow_non_tetrahedral_chirality();
|
||||
test_prop();
|
||||
@@ -2099,6 +2367,11 @@ initRDKitModule().then(function(instance) {
|
||||
test_hs_in_place();
|
||||
test_query_colour();
|
||||
test_alignment_r_groups_aromatic_ring();
|
||||
test_mol_iterator();
|
||||
test_get_num_atoms_bonds();
|
||||
if (RDKitModule.get_mcs_as_mol) {
|
||||
test_mcs();
|
||||
}
|
||||
waitAllTestsFinished().then(() =>
|
||||
console.log("Tests finished successfully")
|
||||
);
|
||||
|
||||
@@ -6,6 +6,14 @@
|
||||
## Highlights
|
||||
|
||||
## Backwards incompatible changes
|
||||
In JS MinimalLib `MolIterator` was renamed to `MolList`: since now it
|
||||
includes `at()`, `append()`, `insert()` and `pop()` methods, `MolIterator`
|
||||
felt inappropriate. This change should have minimal impact on existing
|
||||
JS code since so far there was no constructor for this class.
|
||||
The only place where JS code needs to be updated is when parsing the return
|
||||
value of `JSMol::get_frags()`: the return value consists of an object with
|
||||
two keys, `molIterator` and `mappings`. The `molIterator` key has now
|
||||
been renamed to `molList`.
|
||||
|
||||
## Bug Fixes:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user