- remove redundant #include
- avoid unnecessary copy of match
- expose SubstructMatchParams to JS MinimalLib
- add JS SubstructMatchParams test

Co-authored-by: ptosco <paolo.tosco@novartis.com>
This commit is contained in:
Paolo Tosco
2026-03-26 05:00:42 +01:00
committed by GitHub
parent b56f3dc68a
commit adf060c881
6 changed files with 69 additions and 11 deletions

View File

@@ -11,7 +11,6 @@
#include <RDGeneral/utils.h>
#include <GraphMol/RDKitBase.h>
#include <GraphMol/RDKitQueries.h>
#include <GraphMol/Substruct/SubstructUtils.h>
#include <RDGeneral/BoostStartInclude.h>
#include <boost/dynamic_bitset.hpp>

View File

@@ -390,7 +390,7 @@ extern "C" char *get_substruct_match(const char *mol_pkl, size_t mol_pkl_sz,
std::string res = "{}";
auto matches = SubstructMatch(mol, query, params);
if (!matches.empty()) {
auto match = matches[0];
const auto &match = matches[0];
bj::object doc;
MinimalLib::get_sss_json(mol, query, match, doc);
res = bj::serialize(doc);

View File

@@ -656,8 +656,20 @@ EMSCRIPTEN_BINDINGS(RDKit_minimal) {
get_avalon_fp_as_uint8array))
#endif
#endif
.function("get_substruct_match", &JSMolBase::get_substruct_match)
.function("get_substruct_matches", &JSMolBase::get_substruct_matches)
.function("get_substruct_match",
select_overload<std::string(const JSMolBase &) const>(
&JSMolBase::get_substruct_match))
.function(
"get_substruct_match",
select_overload<std::string(const JSMolBase &, const std::string &)
const>(&JSMolBase::get_substruct_match))
.function("get_substruct_matches",
select_overload<std::string(const JSMolBase &) const>(
&JSMolBase::get_substruct_matches))
.function(
"get_substruct_matches",
select_overload<std::string(const JSMolBase &, const std::string &)
const>(&JSMolBase::get_substruct_matches))
.function("get_descriptors", &JSMolBase::get_descriptors)
.function("get_morgan_fp",
select_overload<std::string() const>(&JSMolBase::get_morgan_fp))

View File

@@ -167,11 +167,17 @@ std::string JSMolBase::get_pickle(const std::string &details) const {
return pickle;
}
std::string JSMolBase::get_substruct_match(const JSMolBase &q) const {
std::string JSMolBase::get_substruct_match(const JSMolBase &q,
const std::string &details) const {
std::string res = "{}";
MatchVectType match;
if (SubstructMatch(get(), q.get(), match)) {
SubstructMatchParameters params;
updateSubstructMatchParamsFromJSON(params, details);
params.maxMatches = 1;
auto matches = SubstructMatch(get(), q.get(), params);
if (!matches.empty()) {
const auto &match = matches[0];
bj::object doc;
MinimalLib::get_sss_json(get(), q.get(), match, doc);
res = bj::serialize(doc);
@@ -180,10 +186,13 @@ std::string JSMolBase::get_substruct_match(const JSMolBase &q) const {
return res;
}
std::string JSMolBase::get_substruct_matches(const JSMolBase &q) const {
std::string JSMolBase::get_substruct_matches(const JSMolBase &q,
const std::string &details) const {
std::string res = "{}";
SubstructMatchParameters params;
updateSubstructMatchParamsFromJSON(params, details);
auto matches = SubstructMatch(get(), q.get());
auto matches = SubstructMatch(get(), q.get(), params);
if (!matches.empty()) {
bj::array doc;

View File

@@ -57,8 +57,16 @@ class JSMolBase {
return get_svg(d_defaultWidth, d_defaultHeight);
}
std::string get_svg_with_highlights(const std::string &details) const;
std::string get_substruct_match(const JSMolBase &q) const;
std::string get_substruct_matches(const JSMolBase &q) const;
std::string get_substruct_match(const JSMolBase &q,
const std::string &details) const;
std::string get_substruct_match(const JSMolBase &q) const {
return get_substruct_match(q, "");
};
std::string get_substruct_matches(const JSMolBase &q,
const std::string &details) const;
std::string get_substruct_matches(const JSMolBase &q) const {
return get_substruct_matches(q, "");
};
std::string get_descriptors() const;
std::string get_morgan_fp(const std::string &details) const;
std::string get_morgan_fp() const { return get_morgan_fp("{}"); }

View File

@@ -4259,6 +4259,35 @@ M END`;
mol.delete();
}
function test_get_substruct_match_params() {
var mol = RDKitModule.get_mol('Br[C@H](F)CCC[C@@H](Br)F');
var query1 = RDKitModule.get_mol('Br[#6@H](C)F');
var query2 = RDKitModule.get_mol('Br[#6@@H](C)F');
assert(mol && query1 && query2);
var res1;
var res2;
res1 = JSON.parse(mol.get_substruct_matches(query1));
res2 = JSON.parse(mol.get_substruct_matches(query2));
assert (res1.length === 2);
assert (res2.length === 2);
res1.sort((a, b) => a.atoms - b.atoms);
res2.sort((a, b) => a.atoms - b.atoms);
assert.equal(JSON.stringify(res1), JSON.stringify(res2));
res1 = JSON.parse(mol.get_substruct_match(query1));
res2 = JSON.parse(mol.get_substruct_match(query2));
assert (!Array.isArray(res1) && !Array.isArray(res2));
assert.equal(JSON.stringify(res1), JSON.stringify(res2));
res1 = JSON.parse(mol.get_substruct_matches(query1, JSON.stringify({ useChirality: true })));
res2 = JSON.parse(mol.get_substruct_matches(query2, JSON.stringify({ useChirality: true })));
assert (res1.length === 1);
assert (res2.length === 1);
assert.notEqual(JSON.stringify(res1), JSON.stringify(res2));
res1 = JSON.parse(mol.get_substruct_match(query1, JSON.stringify({ useChirality: true })));
res2 = JSON.parse(mol.get_substruct_match(query2, JSON.stringify({ useChirality: true })));
assert (!Array.isArray(res1) && !Array.isArray(res2));
assert.notEqual(JSON.stringify(res1), JSON.stringify(res2));
}
initRDKitModule().then(function(instance) {
var done = {};
const waitAllTestsFinished = () => {
@@ -4358,6 +4387,7 @@ initRDKitModule().then(function(instance) {
test_get_coords();
test_get_v3K_v2K_molblock();
test_return_draw_coords();
test_get_substruct_match_params();
waitAllTestsFinished().then(() =>
console.log("Tests finished successfully")