Files
rdkit/Code/DataStructs/Wrap/wrap_FPB.cpp
Paolo Tosco 2b4202867e Add Python modules to generate stubs and automatically patch docstrings (#6919)
* - added gen_rdkit_stubs Python module to generate rdkit-stubs
- added patch_rdkit_docstrings Python module to patch existing C++ sources to fix docstrings missing self parameter and add named parameters taken from C++ signatures where possible
- added rdkit-stubs/CMakeLists.txt to build rdkit-stubs as part of the RDKit build
- added an option to CMakeLists.txt to enable building rdkit-stubs as part of the RDKit build (defaults to OFF)

* fixed CMakeLists.txt, rdkit-stubs/CMakeLists.txt and a doctest

* - added missing cmp_func parameter
- fixed case with overloads with optional parameters
- do not trim params if expected_param_count == -1
- add dummy parameter names if we could not find any
- keep into account member functions when making up parameter names
- address __init__ and make_constructor __init__ functions
- fix incorrectly assigned staticmethods

* patched sources

* address residual few remarks

---------

Co-authored-by: ptosco <paolo.tosco@novartis.com>
2023-11-30 04:54:18 +01:00

208 lines
9.4 KiB
C++

//
// Copyright (C) 2016 greg Landrum
//
// @@ 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 <DataStructs/FPBReader.h>
#include <DataStructs/MultiFPBReader.h>
#include <RDBoost/PySequenceHolder.h>
#include "wrap_helpers.h"
namespace python = boost::python;
using namespace RDKit;
namespace {
python::tuple taniNbrHelper(const FPBReader *self, const std::string &bytes,
double threshold) {
const auto *bv = reinterpret_cast<const std::uint8_t *>(bytes.c_str());
std::vector<std::pair<double, unsigned int>> nbrs =
self->getTanimotoNeighbors(bv, threshold);
python::list result;
for (auto &nbr : nbrs) {
result.append(python::make_tuple(nbr.first, nbr.second));
}
return python::tuple(result);
}
python::tuple tverskyNbrHelper(const FPBReader *self, const std::string &bytes,
double ca, double cb, double threshold) {
const auto *bv = reinterpret_cast<const std::uint8_t *>(bytes.c_str());
std::vector<std::pair<double, unsigned int>> nbrs =
self->getTverskyNeighbors(bv, ca, cb, threshold);
python::list result;
for (auto &nbr : nbrs) {
result.append(python::make_tuple(nbr.first, nbr.second));
}
return python::tuple(result);
}
python::tuple containingNbrHelper(const FPBReader *self,
const std::string &bytes) {
const auto *bv = reinterpret_cast<const std::uint8_t *>(bytes.c_str());
std::vector<unsigned int> nbrs = self->getContainingNeighbors(bv);
python::list result;
for (auto &nbr : nbrs) {
result.append(nbr);
}
return python::tuple(result);
}
python::tuple multiTaniNbrHelper(const MultiFPBReader *self,
const std::string &bytes, double threshold,
unsigned int numThreads) {
const auto *bv = reinterpret_cast<const std::uint8_t *>(bytes.c_str());
std::vector<MultiFPBReader::ResultTuple> nbrs =
self->getTanimotoNeighbors(bv, threshold, numThreads);
python::list result;
for (auto &nbr : nbrs) {
result.append(python::make_tuple(std::get<0>(nbr), std::get<1>(nbr),
std::get<2>(nbr)));
}
return python::tuple(result);
}
python::tuple multiTverskyNbrHelper(const MultiFPBReader *self,
const std::string &bytes, double ca,
double cb, double threshold,
unsigned int numThreads) {
const auto *bv = reinterpret_cast<const std::uint8_t *>(bytes.c_str());
std::vector<MultiFPBReader::ResultTuple> nbrs =
self->getTverskyNeighbors(bv, ca, cb, threshold, numThreads);
python::list result;
for (auto &nbr : nbrs) {
result.append(python::make_tuple(std::get<0>(nbr), std::get<1>(nbr),
std::get<2>(nbr)));
}
return python::tuple(result);
}
python::tuple multiContainingNbrHelper(const MultiFPBReader *self,
const std::string &bytes,
unsigned int numThreads) {
const auto *bv = reinterpret_cast<const std::uint8_t *>(bytes.c_str());
std::vector<std::pair<unsigned int, unsigned int>> nbrs =
self->getContainingNeighbors(bv, numThreads);
python::list result;
for (auto &nbr : nbrs) {
result.append(python::make_tuple(nbr.first, nbr.second));
}
return python::tuple(result);
}
python::object getBytesHelper(const FPBReader *self, unsigned int which) {
boost::shared_array<std::uint8_t> bv = self->getBytes(which);
python::object retval =
python::object(python::handle<>(PyBytes_FromStringAndSize(
reinterpret_cast<const char *>(bv.get()), self->nBits() / 8)));
return retval;
}
double getTaniHelper(const FPBReader *self, unsigned int which,
const std::string &bytes) {
const auto *bv = reinterpret_cast<const std::uint8_t *>(bytes.c_str());
return self->getTanimoto(which, bv);
}
python::tuple getItemHelper(const FPBReader *self, unsigned int which) {
std::pair<boost::shared_ptr<ExplicitBitVect>, std::string> v = (*self)[which];
return python::make_tuple(v.first, v.second);
}
double getTverskyHelper(const FPBReader *self, unsigned int which,
const std::string &bytes, double ca, double cb) {
const auto *bv = reinterpret_cast<const std::uint8_t *>(bytes.c_str());
return self->getTversky(which, bv, ca, cb);
}
} // namespace
struct FPB_wrapper {
static void wrap() {
std::string FPBReaderClassDoc =
"A class for reading and searching FPB files from Andrew Dalke's chemfp.\n\
Note that this functionality is still experimental and the API may\n\
change in future releases.\n";
python::class_<FPBReader, boost::noncopyable>(
"FPBReader", FPBReaderClassDoc.c_str(),
python::init<std::string, python::optional<bool>>(
(python::arg("self"), python::arg("filename"),
python::arg("lazy") = false),
"docstring"))
.def("Init", &FPBReader::init, python::args("self"),
"Read the fingerprints from the file. This can take a while.\n")
.def("__len__", &FPBReader::length, python::args("self"))
.def("__getitem__", &getItemHelper, python::args("self", "which"))
.def("GetNumBits", &FPBReader::nBits, python::args("self"),
"returns the number of bits in a fingerprint")
.def("GetFP", &FPBReader::getFP, python::args("self", "idx"),
"returns a particular fingerprint as an ExplicitBitVect")
.def("GetBytes", &getBytesHelper, python::args("self", "which"),
"returns a particular fingerprint as bytes")
.def("GetId", &FPBReader::getId, python::args("self", "idx"),
"returns the id of a particular fingerprint")
.def("GetTanimoto", &getTaniHelper,
python::args("self", "which", "bytes"),
"return the tanimoto similarity of a particular fingerprint to "
"the bytes provided")
.def("GetTanimotoNeighbors", &taniNbrHelper,
((python::arg("self"), python::arg("bv")),
python::arg("threshold") = 0.7),
"returns tanimoto similarities to and indices of all neighbors "
"above the specified threshold")
.def("GetTversky", &getTverskyHelper,
python::args("self", "which", "bytes", "ca", "cb"),
"return the Tverksy similarity of a particular fingerprint to "
"the bytes provided")
.def("GetTverskyNeighbors", &tverskyNbrHelper,
((python::arg("self"), python::arg("bv")), python::arg("ca"),
python::arg("cb"), python::arg("threshold") = 0.7),
"returns Tversky similarities to and indices of all neighbors "
"above the specified threshold")
.def(
"GetContainingNeighbors", &containingNbrHelper,
((python::arg("self"), python::arg("bv"))),
"returns indices of neighbors that contain this fingerprint (where "
"all bits from this fingerprint are also set)");
std::string MultiFPBReaderClassDoc =
"A class for reading and searching multiple FPB files from Andrew Dalke's chemfp.\n\
Note that this functionality is still experimental and the API may\n\
change in future releases.\n";
python::class_<MultiFPBReader, boost::noncopyable>(
"MultiFPBReader", MultiFPBReaderClassDoc.c_str(),
python::init<python::optional<bool>>(
(python::arg("self"), python::arg("initOnSearch") = false),
"docstring"))
.def("Init", &MultiFPBReader::init, python::args("self"),
"Call Init() on each of our children. This can take a while.\n")
.def("__len__", &MultiFPBReader::length, python::args("self"))
.def("GetNumBits", &MultiFPBReader::nBits, python::args("self"),
"returns the number of bits in a fingerprint")
.def("AddReader", &MultiFPBReader::addReader,
python::with_custodian_and_ward<1, 2>(),
python::args("self", "rdr"),
"adds an FPBReader to our set of readers")
.def("GetReader", &MultiFPBReader::getReader,
python::return_value_policy<python::reference_existing_object>(),
python::args("self", "which"), "returns one of our readers")
.def("GetTanimotoNeighbors", &multiTaniNbrHelper,
((python::arg("self"), python::arg("bv")),
python::arg("threshold") = 0.7, python::arg("numThreads") = 1),
"returns tanimoto similarities to and indices of all neighbors "
"above the specified threshold")
.def("GetTverskyNeighbors", &multiTverskyNbrHelper,
((python::arg("self"), python::arg("bv")), python::arg("ca"),
python::arg("cb"), python::arg("threshold") = 0.7,
python::arg("numThreads") = 1),
"returns Tversky similarities to and indices of all neighbors "
"above the specified threshold")
.def(
"GetContainingNeighbors", &multiContainingNbrHelper,
((python::arg("self"), python::arg("bv")),
python::arg("numThreads") = 1),
"returns indices of neighbors that contain this fingerprint (where "
"all bits from this fingerprint are also set)");
}
};
void wrap_FPB() { FPB_wrapper::wrap(); }