Files
rdkit/Code/GraphMol/TautomerQuery/Wrap/rdTautomerQuery.cpp
Brian Kelley c8cd4e7c20 consolidate numeric vectors (#7792)
* 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
2024-09-18 07:43:17 +02:00

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 &params) {
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 &params) {
return helpGetSubstructMatch(target, self, params);
}
PyObject *tautomerGetSubstructMatchesWithParams(
const TautomerQuery &self, const ROMol &target,
const SubstructMatchParameters &params) {
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 &params) {
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(); }