mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-04 21:54:27 +08:00
* Added fingerprints to GeneralizedSubstruct search * Small change to fire tests * Edits from code review * Updated swig - newobject not required for GeneralizedSubstruct fingerprint methods * GeneralizedSubstruct only supports unique_ptr in SWIG4.1
202 lines
6.7 KiB
C++
202 lines
6.7 KiB
C++
//
|
|
// Copyright (c) 2023, Greg Landrum and other RDKit contributors
|
|
//
|
|
// @@ All Rights Reserved @@
|
|
// This file is part of the RDKit.
|
|
// The contents are covered by the terms of the BSD license
|
|
// which is included in the file license.txt, found at the root
|
|
// of the RDKit source tree.
|
|
//
|
|
//
|
|
|
|
#include <cstdint>
|
|
#include <variant>
|
|
#include <sstream>
|
|
#include <GraphMol/RDKitBase.h>
|
|
#include <GraphMol/MolPickler.h>
|
|
#include <GraphMol/MolBundle.h>
|
|
#include <GraphMol/MolEnumerator/MolEnumerator.h>
|
|
|
|
#include "XQMol.h"
|
|
|
|
#include "GraphMol/Fingerprints/Fingerprints.h"
|
|
|
|
namespace RDKit {
|
|
namespace GeneralizedSubstruct {
|
|
|
|
ExtendedQueryMol::ExtendedQueryMol(const std::string &text, bool isJSON) {
|
|
if (!isJSON) {
|
|
initFromBinary(text);
|
|
} else {
|
|
initFromJSON(text);
|
|
}
|
|
}
|
|
|
|
void ExtendedQueryMol::initFromOther(const ExtendedQueryMol &other) {
|
|
if (std::holds_alternative<ExtendedQueryMol::RWMol_T>(other.xqmol)) {
|
|
xqmol = std::make_unique<RWMol>(
|
|
*std::get<ExtendedQueryMol::RWMol_T>(other.xqmol));
|
|
} else if (std::holds_alternative<ExtendedQueryMol::MolBundle_T>(
|
|
other.xqmol)) {
|
|
xqmol = std::make_unique<MolBundle>(
|
|
*std::get<ExtendedQueryMol::MolBundle_T>(other.xqmol));
|
|
} else if (std::holds_alternative<ExtendedQueryMol::TautomerQuery_T>(
|
|
other.xqmol)) {
|
|
xqmol = std::make_unique<TautomerQuery>(
|
|
*std::get<ExtendedQueryMol::TautomerQuery_T>(other.xqmol));
|
|
} else if (std::holds_alternative<ExtendedQueryMol::TautomerBundle_T>(
|
|
other.xqmol)) {
|
|
auto tb = std::make_unique<std::vector<std::unique_ptr<TautomerQuery>>>();
|
|
for (const auto &tqp :
|
|
*std::get<ExtendedQueryMol::TautomerBundle_T>(other.xqmol)) {
|
|
tb->emplace_back(std::make_unique<TautomerQuery>(*tqp));
|
|
}
|
|
xqmol = std::move(tb);
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<ExplicitBitVect> ExtendedQueryMol::patternFingerprintQuery(
|
|
unsigned fpSize) const {
|
|
if (std::holds_alternative<RWMol_T>(xqmol)) {
|
|
const auto raw = PatternFingerprintMol(*std::get<RWMol_T>(xqmol), fpSize, nullptr,
|
|
nullptr, true);
|
|
std::unique_ptr<ExplicitBitVect> ptr(raw);
|
|
return ptr;
|
|
} if (std::holds_alternative<MolBundle_T>(xqmol)) {
|
|
const auto raw = PatternFingerprintMol(*std::get<MolBundle_T>(xqmol), fpSize, nullptr,
|
|
true);
|
|
std::unique_ptr<ExplicitBitVect> ptr(raw);
|
|
return ptr;
|
|
} if (std::holds_alternative<TautomerQuery_T>(xqmol)) {
|
|
const auto raw = std::get<TautomerQuery_T>(xqmol)->patternFingerprintTemplate(fpSize);
|
|
std::unique_ptr<ExplicitBitVect> ptr(raw);
|
|
return ptr;
|
|
} if (std::holds_alternative<TautomerBundle_T>(xqmol)) {
|
|
const auto &tautomerBundle = std::get<TautomerBundle_T>(xqmol);
|
|
ExplicitBitVect *res = nullptr;
|
|
for (const auto &tautomer : *tautomerBundle) {
|
|
const auto molfp = tautomer->patternFingerprintTemplate(fpSize);
|
|
if (!res) {
|
|
res = molfp;
|
|
} else {
|
|
*res &= *molfp;
|
|
delete molfp;
|
|
}
|
|
}
|
|
std::unique_ptr<ExplicitBitVect> ptr(res);
|
|
return ptr;
|
|
}
|
|
|
|
throw std::invalid_argument("Unknown extended query molecule type");
|
|
}
|
|
|
|
|
|
std::vector<MatchVectType> SubstructMatch(
|
|
const ROMol &mol, const ExtendedQueryMol &query,
|
|
const SubstructMatchParameters ¶ms) {
|
|
std::vector<MatchVectType> res;
|
|
if (std::holds_alternative<ExtendedQueryMol::RWMol_T>(query.xqmol)) {
|
|
res = RDKit::SubstructMatch(
|
|
mol, *std::get<ExtendedQueryMol::RWMol_T>(query.xqmol), params);
|
|
#ifdef RDK_USE_BOOST_SERIALIZATION
|
|
} else if (std::holds_alternative<ExtendedQueryMol::MolBundle_T>(
|
|
query.xqmol)) {
|
|
res = RDKit::SubstructMatch(
|
|
mol, *std::get<ExtendedQueryMol::MolBundle_T>(query.xqmol), params);
|
|
} else if (std::holds_alternative<ExtendedQueryMol::TautomerQuery_T>(
|
|
query.xqmol)) {
|
|
res = std::get<ExtendedQueryMol::TautomerQuery_T>(query.xqmol)
|
|
->substructOf(mol, params);
|
|
} else if (std::holds_alternative<ExtendedQueryMol::TautomerBundle_T>(
|
|
query.xqmol)) {
|
|
const auto &vect =
|
|
std::get<ExtendedQueryMol::TautomerBundle_T>(query.xqmol);
|
|
for (const auto &tq : *vect) {
|
|
res = tq->substructOf(mol, params);
|
|
if (!res.empty()) {
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
} else {
|
|
UNDER_CONSTRUCTION("unrecognized type in ExtendedQueryMol");
|
|
}
|
|
return res;
|
|
}
|
|
|
|
ExtendedQueryMol createExtendedQueryMol(const RWMol &mol, bool doEnumeration,
|
|
bool doTautomers,
|
|
bool adjustQueryProperties,
|
|
MolOps::AdjustQueryParameters params) {
|
|
MolBundle bndl;
|
|
if (doEnumeration) {
|
|
bndl = MolEnumerator::enumerate(mol);
|
|
}
|
|
if (bndl.empty()) {
|
|
// nothing enumerated, just add the input molecule
|
|
bndl.addMol(boost::shared_ptr<ROMol>(new ROMol(mol)));
|
|
}
|
|
|
|
if (bndl.size() == 1) {
|
|
const ROMol *lmol = nullptr;
|
|
std::unique_ptr<ROMol> holder;
|
|
if (adjustQueryProperties) {
|
|
holder.reset(MolOps::adjustQueryProperties(*bndl.getMol(0), ¶ms));
|
|
lmol = holder.get();
|
|
} else {
|
|
lmol = bndl.getMol(0).get();
|
|
}
|
|
if (doTautomers) {
|
|
auto tq = std::unique_ptr<TautomerQuery>(TautomerQuery::fromMol(*lmol));
|
|
if (tq->getTautomers().size() == 1) {
|
|
// no tautomers, just one molecule, return the molecule:
|
|
return {std::make_unique<RWMol>(*lmol)};
|
|
} else {
|
|
// return the tautomers
|
|
return {std::move(tq)};
|
|
}
|
|
} else {
|
|
return {std::make_unique<RWMol>(*lmol)};
|
|
}
|
|
} else {
|
|
MolBundle lbndl;
|
|
for (auto &bmol : bndl.getMols()) {
|
|
if (adjustQueryProperties) {
|
|
boost::shared_ptr<ROMol> lmol(
|
|
MolOps::adjustQueryProperties(*bmol, ¶ms));
|
|
lbndl.addMol(lmol);
|
|
} else {
|
|
lbndl.addMol(bmol);
|
|
}
|
|
}
|
|
bool hadTautomers = false;
|
|
auto tautomerBundle =
|
|
std::make_unique<std::vector<std::unique_ptr<TautomerQuery>>>(0);
|
|
if (doTautomers) {
|
|
for (const auto &bmol : lbndl.getMols()) {
|
|
auto tq = std::unique_ptr<TautomerQuery>(TautomerQuery::fromMol(*bmol));
|
|
if (tq->getTautomers().size() > 1) {
|
|
hadTautomers = true;
|
|
}
|
|
tautomerBundle->emplace_back(std::move(tq));
|
|
}
|
|
}
|
|
if (!hadTautomers) {
|
|
// no tautomers, just return the bundle
|
|
return {std::make_unique<MolBundle>(lbndl)};
|
|
} else {
|
|
// return the tautomer bundle
|
|
return {std::move(tautomerBundle)};
|
|
}
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<ExplicitBitVect> patternFingerprintTargetMol(
|
|
const ROMol& mol, unsigned fpSize) {
|
|
const auto raw= PatternFingerprintMol(mol, fpSize, nullptr, nullptr, true);
|
|
std::unique_ptr<ExplicitBitVect> ptr(raw);
|
|
return ptr;
|
|
}
|
|
} // namespace GeneralizedSubstruct
|
|
} // namespace RDKit
|