mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-07 22:44:25 +08:00
* Speed up boost vector iterators by 300x * Add vector testing code * Update test * Remove GetPosition notebook * Move all wrapped int vectors to top level * Grab MatchTypeVect from rdBase * Actually wrap the vectors
246 lines
9.5 KiB
C++
246 lines
9.5 KiB
C++
//
|
|
// Created by Gareth Jones on 5/30/2020.
|
|
//
|
|
// Copyright 2020-2022 Schrodinger, Inc 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 <RDBoost/Wrap.h>
|
|
#include <RDBoost/python.h>
|
|
#include <GraphMol/TautomerQuery/TautomerQuery.h>
|
|
#include <GraphMol/Wrap/substructmethods.h>
|
|
#include <RDBoost/python_streambuf.h>
|
|
|
|
#define PY_ARRAY_UNIQUE_SYMBOL rdtautomerquery_array_API
|
|
|
|
namespace python = boost::python;
|
|
using boost_adaptbx::python::streambuf;
|
|
using namespace RDKit;
|
|
|
|
namespace {
|
|
|
|
TautomerQuery *createDefaultTautomerQuery(const ROMol &mol) {
|
|
return TautomerQuery::fromMol(mol);
|
|
}
|
|
|
|
bool tautomerIsSubstructOf(const TautomerQuery &self, const ROMol &target,
|
|
bool recursionPossible = true,
|
|
bool useChirality = false,
|
|
bool useQueryQueryMatches = false) {
|
|
return HasSubstructMatch(target, self, recursionPossible, useChirality,
|
|
useQueryQueryMatches);
|
|
}
|
|
|
|
bool tautomerIsSubstructOfWithParams(const TautomerQuery &self,
|
|
const ROMol &target,
|
|
const SubstructMatchParameters ¶ms) {
|
|
return helpHasSubstructMatch(target, self, params);
|
|
}
|
|
|
|
PyObject *tautomerGetSubstructMatch(const TautomerQuery &self,
|
|
const ROMol &target,
|
|
bool useChirality = false,
|
|
bool useQueryQueryMatches = false) {
|
|
return GetSubstructMatch(target, self, useChirality, useQueryQueryMatches);
|
|
}
|
|
|
|
PyObject *tautomerGetSubstructMatchWithParams(
|
|
const TautomerQuery &self, const ROMol &target,
|
|
const SubstructMatchParameters ¶ms) {
|
|
return helpGetSubstructMatch(target, self, params);
|
|
}
|
|
|
|
PyObject *tautomerGetSubstructMatchesWithParams(
|
|
const TautomerQuery &self, const ROMol &target,
|
|
const SubstructMatchParameters ¶ms) {
|
|
return helpGetSubstructMatches(target, self, params);
|
|
}
|
|
|
|
PyObject *tautomerGetSubstructMatches(const TautomerQuery &self,
|
|
const ROMol &target, bool uniquify = true,
|
|
bool useChirality = false,
|
|
bool useQueryQueryMatches = false,
|
|
unsigned int maxMatches = 1000) {
|
|
return GetSubstructMatches(target, self, uniquify, useChirality,
|
|
useQueryQueryMatches, maxMatches);
|
|
}
|
|
|
|
PyObject *getTautomers(const TautomerQuery &self) {
|
|
auto tauts = self.getTautomers();
|
|
auto nTauts = tauts.size();
|
|
auto tuple = PyTuple_New(nTauts);
|
|
for (size_t i = 0; i < nTauts; i++) {
|
|
PyTuple_SetItem(tuple, i,
|
|
python::converter::shared_ptr_to_python(tauts[i]));
|
|
}
|
|
return tuple;
|
|
}
|
|
|
|
PyObject *matchesWithTautomersToTuple(std::vector<MatchVectType> &matches,
|
|
const MOL_SPTR_VECT &matchingTautomers) {
|
|
int const numberMatches = matches.size();
|
|
PyObject *res = PyTuple_New(numberMatches);
|
|
for (int idx = 0; idx < numberMatches; idx++) {
|
|
PyObject *pair = PyTuple_New(2);
|
|
PyTuple_SetItem(pair, 0, convertMatches(matches[idx]));
|
|
PyTuple_SetItem(
|
|
pair, 1,
|
|
python::converter::shared_ptr_to_python(matchingTautomers[idx]));
|
|
PyTuple_SetItem(res, idx, pair);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
PyObject *tautomerGetSubstructMatchesWithTautomersWithParams(
|
|
const TautomerQuery &self, const ROMol &target,
|
|
const SubstructMatchParameters ¶ms) {
|
|
std::vector<MatchVectType> matches;
|
|
std::vector<ROMOL_SPTR> matchingTautomers;
|
|
|
|
if (params.extraFinalCheck) {
|
|
// NOTE: Because we are going into/out of python here, we can't
|
|
// run with NOGIL
|
|
matches = self.substructOf(target, params, &matchingTautomers);
|
|
} else {
|
|
NOGIL gil;
|
|
|
|
matches = self.substructOf(target, params, &matchingTautomers);
|
|
}
|
|
|
|
return matchesWithTautomersToTuple(matches, matchingTautomers);
|
|
}
|
|
|
|
PyObject *tautomerGetSubstructMatchesWithTautomers(
|
|
const TautomerQuery &self, const ROMol &target, bool uniquify = true,
|
|
bool useChirality = false, bool useQueryQueryMatches = false,
|
|
unsigned int maxMatches = 1000) {
|
|
std::vector<MatchVectType> matches;
|
|
std::vector<ROMOL_SPTR> matchingTautomers;
|
|
SubstructMatchParameters params;
|
|
params.uniquify = uniquify;
|
|
params.useChirality = useChirality;
|
|
params.useQueryQueryMatches = useQueryQueryMatches;
|
|
params.maxMatches = maxMatches;
|
|
|
|
{
|
|
NOGIL gil;
|
|
|
|
matches = self.substructOf(target, params, &matchingTautomers);
|
|
}
|
|
return matchesWithTautomersToTuple(matches, matchingTautomers);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
namespace RDKit {
|
|
struct tautomerquery_pickle_suite : rdkit_pickle_suite {
|
|
static python::tuple getinitargs(const TautomerQuery &self) {
|
|
if (!TautomerQueryCanSerialize()) {
|
|
throw_runtime_error("Pickling of TautomerQuery instances is not enabled");
|
|
}
|
|
auto res = self.serialize();
|
|
return python::make_tuple(python::object(python::handle<>(
|
|
PyBytes_FromStringAndSize(res.c_str(), res.length()))));
|
|
};
|
|
};
|
|
|
|
void toStream(const TautomerQuery &tq, python::object &fileobj) {
|
|
streambuf ss(fileobj, 't');
|
|
streambuf::ostream ost(ss);
|
|
tq.toStream(ost);
|
|
}
|
|
|
|
void initFromStream(TautomerQuery &tq, python::object &fileobj) {
|
|
streambuf ss(fileobj,
|
|
'b'); // python StringIO can't seek, so need binary data
|
|
streambuf::istream is(ss);
|
|
tq.initFromStream(is);
|
|
}
|
|
|
|
python::object TQToBinary(const TautomerQuery &tq) {
|
|
auto res = tq.serialize();
|
|
return python::object(
|
|
python::handle<>(PyBytes_FromStringAndSize(res.c_str(), res.length())));
|
|
}
|
|
} // namespace RDKit
|
|
|
|
struct TautomerQuery_wrapper {
|
|
static void wrap() {
|
|
auto docString =
|
|
"The Tautomer Query Class.\n\
|
|
Creates a query that enables structure search accounting for matching of\n\
|
|
Tautomeric forms\n";
|
|
|
|
python::class_<TautomerQuery, boost::noncopyable>(
|
|
"TautomerQuery", docString, python::no_init)
|
|
.def("__init__", python::make_constructor(createDefaultTautomerQuery))
|
|
.def("__init__", python::make_constructor(&TautomerQuery::fromMol))
|
|
.def(python::init<std::string>(python::args("self", "pickle")))
|
|
.def("IsSubstructOf", tautomerIsSubstructOf,
|
|
(python::arg("self"), python::arg("target"),
|
|
python::arg("recursionPossible") = true,
|
|
python::arg("useChirality") = false,
|
|
python::arg("useQueryQueryMatches") = false))
|
|
.def(
|
|
"IsSubstructOf", tautomerIsSubstructOfWithParams,
|
|
(python::arg("self"), python::arg("target"), python::arg("params")))
|
|
.def("GetSubstructMatch", tautomerGetSubstructMatch,
|
|
(python::arg("self"), python::arg("target"),
|
|
python::arg("useChirality") = false,
|
|
python::arg("useQueryQueryMatches") = false))
|
|
.def(
|
|
"GetSubstructMatch", tautomerGetSubstructMatchWithParams,
|
|
(python::arg("self"), python::arg("target"), python::arg("params")))
|
|
.def("GetSubstructMatches", tautomerGetSubstructMatches,
|
|
(python::arg("self"), python::arg("target"),
|
|
python::arg("uniquify") = true,
|
|
python::arg("useChirality") = false,
|
|
python::arg("useQueryQueryMatches") = false,
|
|
python::arg("maxMatches") = 1000))
|
|
.def(
|
|
"GetSubstructMatches", tautomerGetSubstructMatchesWithParams,
|
|
(python::arg("self"), python::arg("target"), python::arg("params")))
|
|
.def("GetSubstructMatchesWithTautomers",
|
|
tautomerGetSubstructMatchesWithTautomers,
|
|
(python::arg("self"), python::arg("target"),
|
|
python::arg("uniquify") = true,
|
|
python::arg("useChirality") = false,
|
|
python::arg("useQueryQueryMatches") = false,
|
|
python::arg("maxMatches") = 1000))
|
|
.def(
|
|
"GetSubstructMatchesWithTautomers",
|
|
tautomerGetSubstructMatchesWithTautomersWithParams,
|
|
(python::arg("self"), python::arg("target"), python::arg("params")))
|
|
.def("PatternFingerprintTemplate",
|
|
&TautomerQuery::patternFingerprintTemplate,
|
|
((python::arg("self"), python::arg("fingerprintSize") = 2048)),
|
|
python::return_value_policy<python::manage_new_object>())
|
|
.def("GetTemplateMolecule", &TautomerQuery::getTemplateMolecule,
|
|
python::return_internal_reference<>(), python::args("self"))
|
|
.def("GetModifiedAtoms", &TautomerQuery::getModifiedAtoms,
|
|
python::args("self"))
|
|
.def("GetModifiedBonds", &TautomerQuery::getModifiedBonds,
|
|
python::args("self"))
|
|
.def("GetTautomers", getTautomers, python::args("self"))
|
|
.def("ToBinary", TQToBinary, python::args("self"))
|
|
.def_pickle(tautomerquery_pickle_suite());
|
|
|
|
python::def("PatternFingerprintTautomerTarget",
|
|
&TautomerQuery::patternFingerprintTarget,
|
|
(python::arg("target"), python::arg("fingerprintSize") = 2048),
|
|
python::return_value_policy<python::manage_new_object>());
|
|
|
|
python::def(
|
|
"TautomerQueryCanSerialize", TautomerQueryCanSerialize,
|
|
"Returns True if the TautomerQuery is serializable "
|
|
"(requires that the RDKit was built with boost::serialization)");
|
|
}
|
|
};
|
|
|
|
void wrap_TautomerQuery() { TautomerQuery_wrapper::wrap(); }
|
|
|
|
BOOST_PYTHON_MODULE(rdTautomerQuery) { wrap_TautomerQuery(); }
|