Files
rdkit/Code/GraphMol/Wrap/Mol.cpp
Greg Landrum da6cd73168 Run clang-format across everything (#7849)
* run clang-format-18 across Code/*.cpp and Code/*.h

* run clang-format-18 across External
2024-09-26 13:39:02 +02:00

922 lines
41 KiB
C++

// Copyright (C) 2003-2017 Greg Landrum and Rational Discovery LLC
//
// @@ 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.
//
#define NO_IMPORT_ARRAY
#include <RDBoost/python.h>
#include <string>
#include "props.hpp"
#include "rdchem.h"
#include "seqs.hpp"
#include "substructmethods.h"
// ours
#include <GraphMol/MolBundle.h>
#include <GraphMol/MolPickler.h>
#include <GraphMol/QueryOps.h>
#include <GraphMol/RDKitBase.h>
#include <GraphMol/SmilesParse/SmilesParse.h>
#include <GraphMol/Substruct/SubstructMatch.h>
#include <RDBoost/Wrap.h>
#include <RDBoost/pyint_api.h>
#include <boost/python/copy_non_const_reference.hpp>
#include <boost/python/iterator.hpp>
namespace python = boost::python;
namespace RDKit {
void MolClearComputedPropsHelper(const ROMol &mol, bool includeRings) {
mol.clearComputedProps(includeRings);
}
python::object MolToBinary(const ROMol &self) {
std::string res;
{
NOGIL gil;
MolPickler::pickleMol(self, res);
}
python::object retval = python::object(
python::handle<>(PyBytes_FromStringAndSize(res.c_str(), res.length())));
return retval;
}
python::object MolToBinaryWithProps(const ROMol &self, unsigned int props) {
std::string res;
{
NOGIL gil;
MolPickler::pickleMol(self, res, props);
}
python::object retval = python::object(
python::handle<>(PyBytes_FromStringAndSize(res.c_str(), res.length())));
return retval;
}
//
// allows molecules to be pickled.
// since molecules have a constructor that takes a binary string
// we only need to provide getinitargs()
//
struct mol_pickle_suite : rdkit_pickle_suite {
static python::tuple getinitargs(const ROMol &self) {
return python::make_tuple(MolToBinary(self));
};
};
bool HasSubstructMatchStr(std::string pkl, const ROMol &query,
bool recursionPossible = true,
bool useChirality = false,
bool useQueryQueryMatches = false) {
NOGIL gil;
ROMol *mol;
try {
mol = new ROMol(pkl);
} catch (...) {
mol = nullptr;
}
if (!mol) {
throw ValueErrorException("Null Molecule");
}
MatchVectType res;
bool hasM = SubstructMatch(*mol, query, res, recursionPossible, useChirality,
useQueryQueryMatches);
delete mol;
return hasM;
}
unsigned int AddMolConformer(ROMol &mol, Conformer *conf,
bool assignId = false) {
auto *nconf = new Conformer(*conf);
return mol.addConformer(nconf, assignId);
}
Conformer *GetMolConformer(ROMol &mol, int id = -1) {
return &(mol.getConformer(id));
}
void MolDebug(const ROMol &mol, bool useStdout) {
if (useStdout) {
mol.debugMol(std::cout);
} else {
std::ostream *dest = &std::cerr;
if (rdInfoLog != nullptr) {
if (rdInfoLog->teestream) {
dest = rdInfoLog->teestream;
} else if (rdInfoLog->dp_dest) {
dest = rdInfoLog->dp_dest;
}
mol.debugMol(*dest);
}
}
}
// FIX: we should eventually figure out how to do iterators properly
QueryAtomIterSeq *MolGetAromaticAtoms(const ROMOL_SPTR &mol) {
auto *qa = new QueryAtom();
qa->setQuery(makeAtomAromaticQuery());
QueryAtomIterSeq *res =
new QueryAtomIterSeq(mol, mol->beginQueryAtoms(qa), mol->endQueryAtoms(),
AtomCountFunctor(mol));
return res;
}
QueryAtomIterSeq *MolGetQueryAtoms(const ROMOL_SPTR &mol, QueryAtom *qa) {
QueryAtomIterSeq *res =
new QueryAtomIterSeq(mol, mol->beginQueryAtoms(qa), mol->endQueryAtoms(),
AtomCountFunctor(mol));
return res;
}
ConformerIterSeq *GetMolConformers(const ROMOL_SPTR &mol) {
ConformerIterSeq *res =
new ConformerIterSeq(mol, mol->beginConformers(), mol->endConformers(),
ConformerCountFunctor(mol));
return res;
}
int getMolNumAtoms(const ROMol &mol, int onlyHeavy, bool onlyExplicit) {
if (onlyHeavy > -1) {
BOOST_LOG(rdWarningLog)
<< "WARNING: the onlyHeavy argument to mol.GetNumAtoms() has been "
"deprecated. Please use the onlyExplicit argument instead or "
"mol.GetNumHeavyAtoms() if you want the heavy atom count."
<< std::endl;
return mol.getNumAtoms(onlyHeavy);
}
return mol.getNumAtoms(onlyExplicit);
}
namespace {
class pyobjFunctor {
public:
pyobjFunctor(python::object obj) : dp_obj(std::move(obj)) {}
~pyobjFunctor() = default;
bool operator()(const ROMol &m, const std::vector<unsigned int> &match) {
return python::extract<bool>(dp_obj(boost::ref(m), boost::ref(match)));
}
private:
python::object dp_obj;
};
void setSubstructMatchFinalCheck(SubstructMatchParameters &ps,
python::object func) {
ps.extraFinalCheck = pyobjFunctor(func);
}
} // namespace
class ReadWriteMol : public RWMol {
public:
ReadWriteMol() {};
ReadWriteMol(const ROMol &m, bool quickCopy = false, int confId = -1)
: RWMol(m, quickCopy, confId) {};
void RemoveAtom(unsigned int idx) { removeAtom(idx); };
void RemoveBond(unsigned int idx1, unsigned int idx2) {
removeBond(idx1, idx2);
};
int AddBond(unsigned int begAtomIdx, unsigned int endAtomIdx,
Bond::BondType order = Bond::UNSPECIFIED) {
return addBond(begAtomIdx, endAtomIdx, order);
};
int AddAtom(Atom *atom) {
PRECONDITION(atom, "bad atom");
return addAtom(atom, true, false);
};
void ReplaceAtom(unsigned int idx, Atom *atom, bool updateLabel,
bool preserveProps) {
PRECONDITION(atom, "bad atom");
replaceAtom(idx, atom, updateLabel, preserveProps);
};
void ReplaceBond(unsigned int idx, Bond *bond, bool preserveProps,
bool keepSGroups) {
PRECONDITION(bond, "bad bond");
replaceBond(idx, bond, preserveProps, keepSGroups);
};
void SetStereoGroups(python::list &stereo_groups) {
std::vector<StereoGroup> groups;
pythonObjectToVect<StereoGroup>(stereo_groups, groups);
for (const auto &group : groups) {
for (const auto atom : group.getAtoms()) {
if (!atom) {
throw_value_error("NULL atom in StereoGroup");
}
if (&atom->getOwningMol() != this) {
throw_value_error(
"atom in StereoGroup does not belong to this molecule.");
}
}
}
setStereoGroups(std::move(groups));
}
ROMol *GetMol() const {
auto *res = new ROMol(*this);
return res;
}
ReadWriteMol *enter() {
beginBatchEdit();
return this;
}
bool exit(python::object exc_type, python::object exc_val,
python::object traceback) {
RDUNUSED_PARAM(exc_val);
RDUNUSED_PARAM(traceback);
if (exc_type != python::object()) {
// exception thrown, abort the edits
rollbackBatchEdit();
} else {
commitBatchEdit();
}
// we haven't handled any possible exceptions (and shouldn't do so),
// so just return false;
return false;
}
private:
boost::shared_ptr<RWMol> dp_mol;
};
std::string molClassDoc =
"The Molecule class.\n\n\
In addition to the expected Atoms and Bonds, molecules contain:\n\
- a collection of Atom and Bond bookmarks indexed with integers\n\
that can be used to flag and retrieve particular Atoms or Bonds\n\
using the {get|set}{Atom|Bond}Bookmark() methods.\n\n\
- a set of string-valued properties. These can have arbitrary string\n\
labels and can be set and retrieved using the {set|get}Prop() methods\n\
Molecular properties can be tagged as being *computed*, in which case\n\
they will be automatically cleared under certain circumstances (when the\n\
molecule itself is modified, for example).\n\
Molecules also have the concept of *private* properties, which are tagged\n\
by beginning the property name with an underscore (_).\n";
std::string rwmolClassDoc =
"The RW molecule class (read/write)\n\n\
This class is a more-performant version of the EditableMolecule class in that\n\
it is a 'live' molecule and shares the interface from the Mol class.\n\
All changes are performed without the need to create a copy of the\n\
molecule using GetMol() (this is still available, however).\n\
\n\
n.b. Eventually this class may become a direct replacement for EditableMol";
struct mol_wrapper {
static void wrap() {
python::register_exception_translator<ConformerException>(
&rdExceptionTranslator);
python::enum_<RDKit::PicklerOps::PropertyPickleOptions>(
"PropertyPickleOptions")
.value("NoProps", RDKit::PicklerOps::NoProps)
.value("MolProps", RDKit::PicklerOps::MolProps)
.value("AtomProps", RDKit::PicklerOps::AtomProps)
.value("BondProps", RDKit::PicklerOps::BondProps)
.value("QueryAtomData", RDKit::PicklerOps::QueryAtomData)
.value("PrivateProps", RDKit::PicklerOps::PrivateProps)
.value("ComputedProps", RDKit::PicklerOps::ComputedProps)
.value("AllProps", RDKit::PicklerOps::AllProps)
.value("CoordsAsDouble", RDKit::PicklerOps::CoordsAsDouble)
.value("NoConformers", RDKit::PicklerOps::NoConformers)
.export_values();
;
RegisterVectorConverter<StereoGroup>("StereoGroup_vect");
python::def("GetDefaultPickleProperties",
MolPickler::getDefaultPickleProperties,
"Get the current global mol pickler options.");
python::def("SetDefaultPickleProperties",
MolPickler::setDefaultPickleProperties, python::args("arg1"),
"Set the current global mol pickler options.");
// REVIEW: There's probably a better place for this definition
python::class_<RDKit::SubstructMatchParameters, boost::noncopyable>(
"SubstructMatchParameters",
"Parameters controlling substructure matching")
.def_readwrite(
"useChirality", &RDKit::SubstructMatchParameters::useChirality,
"Use chirality in determining whether or not atoms/bonds match")
.def_readwrite(
"useEnhancedStereo",
&RDKit::SubstructMatchParameters::useEnhancedStereo,
"take enhanced stereochemistry into account while doing the match. "
"This only has an effect if useChirality is also True.")
.def_readwrite(
"aromaticMatchesConjugated",
&RDKit::SubstructMatchParameters::aromaticMatchesConjugated,
"aromatic and conjugated bonds match each other")
.def_readwrite(
"useGenericMatchers",
&RDKit::SubstructMatchParameters::useGenericMatchers,
"use generic groups (=homology groups) as a post-filtering step "
"(if any are present in the molecule)")
.def_readwrite("useQueryQueryMatches",
&RDKit::SubstructMatchParameters::useQueryQueryMatches,
"Consider query-query matches, not just simple matches")
.def_readwrite("recursionPossible",
&RDKit::SubstructMatchParameters::recursionPossible,
"Allow recursive queries")
.def_readwrite("uniquify", &RDKit::SubstructMatchParameters::uniquify,
"uniquify (by atom index) match results")
.def_readwrite("maxMatches",
&RDKit::SubstructMatchParameters::maxMatches,
"maximum number of matches to return")
.def_readwrite("maxRecursiveMatches",
&RDKit::SubstructMatchParameters::maxRecursiveMatches,
"maximum number of recursive matches to find")
.def_readwrite(
"numThreads", &RDKit::SubstructMatchParameters::numThreads,
"number of threads to use when multi-threading is possible."
"0 selects the number of concurrent threads supported by the"
"hardware. negative values are added to the number of concurrent"
"threads supported by the hardware.")
.def_readwrite(
"atomProperties", &RDKit::SubstructMatchParameters::atomProperties,
"atom properties that must be equivalent in order to match.")
.def_readwrite(
"bondProperties", &RDKit::SubstructMatchParameters::bondProperties,
"bond properties that must be equivalent in order to match.")
.def("setExtraFinalCheck", setSubstructMatchFinalCheck,
python::with_custodian_and_ward<1, 2>(),
python::args("self", "func"),
R"DOC(allows you to provide a function that will be called
with the molecule
and a vector of atom IDs containing a potential match.
The function should return true or false indicating whether or not
that match should be accepted.)DOC");
python::class_<ROMol, ROMOL_SPTR, boost::noncopyable>(
"Mol", molClassDoc.c_str(),
python::init<>(python::args("self"), "Constructor, takes no arguments"))
.def(python::init<const std::string &>(
python::args("self", "pklString")))
.def(python::init<const std::string &, unsigned int>(
(python::args("self", "pklString", "propertyFlags"))))
.def(python::init<const ROMol &, bool, int>(
(python::arg("self"), python::arg("mol"),
python::arg("quickCopy") = false, python::arg("confId") = -1)))
.def("__copy__", &generic__copy__<ROMol>, python::args("self"))
.def("__deepcopy__", &generic__deepcopy__<ROMol>,
python::args("self", "memo"))
.def("GetNumAtoms", getMolNumAtoms,
((python::arg("self"), python::arg("onlyHeavy") = -1),
python::arg("onlyExplicit") = true),
"Returns the number of atoms in the molecule.\n\n"
" ARGUMENTS:\n"
" - onlyExplicit: (optional) include only explicit atoms "
"(atoms in the molecular graph)\n"
" defaults to 1.\n"
" NOTE: the onlyHeavy argument is deprecated\n"
)
.def("GetNumHeavyAtoms", &ROMol::getNumHeavyAtoms, python::args("self"),
"Returns the number of heavy atoms (atomic number >1) in the "
"molecule.\n\n")
.def("GetAtomWithIdx",
(Atom * (ROMol::*)(unsigned int)) & ROMol::getAtomWithIdx,
python::return_internal_reference<
1, python::with_custodian_and_ward_postcall<0, 1>>(),
python::args("self", "idx"),
"Returns a particular Atom.\n\n"
" ARGUMENTS:\n"
" - idx: which Atom to return\n\n"
" NOTE: atom indices start at 0\n")
.def("GetNumBonds", &ROMol::getNumBonds,
((python::arg("self"), python::arg("onlyHeavy") = true)),
"Returns the number of Bonds in the molecule.\n\n"
" ARGUMENTS:\n"
" - onlyHeavy: (optional) include only bonds to heavy atoms "
"(not Hs)\n"
" defaults to 1.\n")
.def("GetBondWithIdx",
(Bond * (ROMol::*)(unsigned int)) & ROMol::getBondWithIdx,
python::return_internal_reference<
1, python::with_custodian_and_ward_postcall<0, 1>>(),
python::args("self", "idx"),
"Returns a particular Bond.\n\n"
" ARGUMENTS:\n"
" - idx: which Bond to return\n\n"
" NOTE: bond indices start at 0\n")
.def("GetNumConformers", &ROMol::getNumConformers, python::args("self"),
"Return the number of conformations on the molecule")
.def("AddConformer", AddMolConformer,
(python::arg("self"), python::arg("conf"),
python::arg("assignId") = false),
"Add a conformer to the molecule and return the conformer ID")
#if 0
.def("AddConformersFromTrajectory", &ROMol::addConformersFromTrajectory,
(python::arg("self"), python::arg("traj"),
python::arg("nConf") = -1),
"Add conformers from a Trajectory to the molecule and return\n"
"the number of conformations that were added")
#endif
.def("GetConformer", GetMolConformer,
(python::arg("self"), python::arg("id") = -1),
"Get the conformer with a specified ID",
python::return_internal_reference<
1, python::with_custodian_and_ward_postcall<0, 1>>())
.def("GetConformers", GetMolConformers,
python::return_value_policy<
python::manage_new_object,
python::with_custodian_and_ward_postcall<0, 1>>(),
python::args("self"),
"Returns a read-only sequence containing all of the molecule's "
"Conformers.")
.def("RemoveAllConformers", &ROMol::clearConformers,
python::args("self"),
"Remove all the conformations on the molecule")
.def("RemoveConformer", &ROMol::removeConformer,
python::args("self", "id"),
"Remove the conformer with the specified ID")
.def("GetBondBetweenAtoms",
(Bond * (ROMol::*)(unsigned int, unsigned int)) &
ROMol::getBondBetweenAtoms,
python::return_internal_reference<
1, python::with_custodian_and_ward_postcall<0, 1>>(),
python::args("self", "idx1", "idx2"),
"Returns the bond between two atoms, if there is one.\n\n"
" ARGUMENTS:\n"
" - idx1,idx2: the Atom indices\n\n"
" Returns:\n"
" The Bond between the two atoms, if such a bond exists.\n"
" If there is no Bond between the atoms, None is returned "
"instead.\n\n"
" NOTE: bond indices start at 0\n")
.def("HasQuery", &ROMol::hasQuery, python::args("self"),
"Returns if any atom or bond in molecule has a query")
// substructures
.def("HasSubstructMatch",
(bool (*)(const ROMol &m, const ROMol &query, bool, bool,
bool))HasSubstructMatch,
(python::arg("self"), python::arg("query"),
python::arg("recursionPossible") = true,
python::arg("useChirality") = false,
python::arg("useQueryQueryMatches") = false),
"Queries whether or not the molecule contains a particular "
"substructure.\n\n"
" ARGUMENTS:\n"
" - query: a Molecule\n\n"
" - recursionPossible: (optional)\n\n"
" - useChirality: enables the use of stereochemistry in the "
"matching\n\n"
" - useQueryQueryMatches: use query-query matching logic\n\n"
" RETURNS: True or False\n")
.def("GetSubstructMatch",
(PyObject * (*)(const ROMol &m, const ROMol &query, bool, bool))
GetSubstructMatch,
(python::arg("self"), python::arg("query"),
python::arg("useChirality") = false,
python::arg("useQueryQueryMatches") = false),
"Returns the indices of the molecule's atoms that match a "
"substructure query.\n\n"
" ARGUMENTS:\n"
" - query: a Molecule\n\n"
" - useChirality: enables the use of stereochemistry in the "
"matching\n\n"
" - useQueryQueryMatches: use query-query matching logic\n\n"
" RETURNS: a tuple of integers\n\n"
" NOTES:\n"
" - only a single match is returned\n"
" - the ordering of the indices corresponds to the atom "
"ordering\n"
" in the query. For example, the first index is for the "
"atom in\n"
" this molecule that matches the first atom in the "
"query.\n")
.def("GetSubstructMatches",
(PyObject * (*)(const ROMol &m, const ROMol &query, bool, bool,
bool, unsigned int)) GetSubstructMatches,
(python::arg("self"), python::arg("query"),
python::arg("uniquify") = true,
python::arg("useChirality") = false,
python::arg("useQueryQueryMatches") = false,
python::arg("maxMatches") = 1000),
"Returns tuples of the indices of the molecule's atoms that "
"match "
"a substructure query.\n\n"
" ARGUMENTS:\n"
" - query: a Molecule.\n"
" - uniquify: (optional) determines whether or not the "
"matches "
"are uniquified.\n"
" Defaults to 1.\n\n"
" - useChirality: enables the use of stereochemistry in the "
"matching\n\n"
" - useQueryQueryMatches: use query-query matching logic\n\n"
" - maxMatches: The maximum number of matches that will be "
"returned.\n"
" In high-symmetry cases with medium-sized "
"molecules, it is\n"
" very easy to end up with a combinatorial "
"explosion in the\n"
" number of possible matches. This argument "
"prevents that from\n"
" having unintended consequences\n\n"
" RETURNS: a tuple of tuples of integers\n\n"
" NOTE:\n"
" - the ordering of the indices corresponds to the atom "
"ordering\n"
" in the query. For example, the first index is for the "
"atom in\n"
" this molecule that matches the first atom in the "
"query.\n")
.def("HasSubstructMatch",
(bool (*)(const ROMol &m, const MolBundle &query, bool, bool,
bool))HasSubstructMatch,
(python::arg("self"), python::arg("query"),
python::arg("recursionPossible") = true,
python::arg("useChirality") = false,
python::arg("useQueryQueryMatches") = false))
.def("GetSubstructMatch",
(PyObject * (*)(const ROMol &m, const MolBundle &query, bool,
bool)) GetSubstructMatch,
(python::arg("self"), python::arg("query"),
python::arg("useChirality") = false,
python::arg("useQueryQueryMatches") = false))
.def("GetSubstructMatches",
(PyObject * (*)(const ROMol &m, const MolBundle &query, bool, bool,
bool, unsigned int)) GetSubstructMatches,
(python::arg("self"), python::arg("query"),
python::arg("uniquify") = true,
python::arg("useChirality") = false,
python::arg("useQueryQueryMatches") = false,
python::arg("maxMatches") = 1000))
//--------------------------------------------
.def("HasSubstructMatch",
(bool (*)(const ROMol &m, const ROMol &query,
const SubstructMatchParameters &))helpHasSubstructMatch,
(python::arg("self"), python::arg("query"), python::arg("params")),
"Queries whether or not the molecule contains a particular "
"substructure.\n\n"
" ARGUMENTS:\n"
" - query: a Molecule\n\n"
" - params: parameters controlling the substructure match\n\n"
" RETURNS: True or False\n")
.def("GetSubstructMatch",
(PyObject * (*)(const ROMol &m, const ROMol &query,
const SubstructMatchParameters &params))
helpGetSubstructMatch,
(python::arg("self"), python::arg("query"), python::arg("params")),
"Returns the indices of the molecule's atoms that match a "
"substructure query.\n\n"
" ARGUMENTS:\n"
" - query: a Molecule\n\n"
" - params: parameters controlling the substructure match\n\n"
" RETURNS: a tuple of integers\n\n"
" NOTES:\n"
" - only a single match is returned\n"
" - the ordering of the indices corresponds to the atom "
"ordering\n"
" in the query. For example, the first index is for the "
"atom in\n"
" this molecule that matches the first atom in the "
"query.\n")
.def("GetSubstructMatches",
(PyObject * (*)(const ROMol &m, const ROMol &query,
const SubstructMatchParameters &))
helpGetSubstructMatches,
(python::arg("self"), python::arg("query"), python::arg("params")),
"Returns tuples of the indices of the molecule's atoms that "
"match "
"a substructure query.\n\n"
" ARGUMENTS:\n"
" - query: a Molecule.\n"
" - params: parameters controlling the substructure match\n\n"
" RETURNS: a tuple of tuples of integers\n\n"
" NOTE:\n"
" - the ordering of the indices corresponds to the atom "
"ordering\n"
" in the query. For example, the first index is for the "
"atom in\n"
" this molecule that matches the first atom in the "
"query.\n")
.def("HasSubstructMatch",
(bool (*)(const ROMol &m, const MolBundle &query,
const SubstructMatchParameters &))helpHasSubstructMatch,
(python::arg("self"), python::arg("query"),
python::arg("params") = true))
.def("GetSubstructMatch",
(PyObject * (*)(const ROMol &m, const MolBundle &query,
const SubstructMatchParameters &))
helpGetSubstructMatch,
(python::arg("self"), python::arg("query"), python::arg("params")))
.def("GetSubstructMatches",
(PyObject * (*)(const ROMol &m, const MolBundle &query,
const SubstructMatchParameters &))
helpGetSubstructMatches,
(python::arg("self"), python::arg("query"), python::arg("params")))
// properties
.def("SetProp", MolSetProp<ROMol, std::string>,
(python::arg("self"), python::arg("key"), python::arg("val"),
python::arg("computed") = false),
"Sets a molecular property\n\n"
" ARGUMENTS:\n"
" - key: the name of the property to be set (a string).\n"
" - value: the property value (a string).\n"
" - computed: (optional) marks the property as being "
"computed.\n"
" Defaults to False.\n\n")
.def("SetDoubleProp", MolSetProp<ROMol, double>,
(python::arg("self"), python::arg("key"), python::arg("val"),
python::arg("computed") = false),
"Sets a double valued molecular property\n\n"
" ARGUMENTS:\n"
" - key: the name of the property to be set (a string).\n"
" - value: the property value as a double.\n"
" - computed: (optional) marks the property as being "
"computed.\n"
" Defaults to 0.\n\n")
.def("SetIntProp", MolSetProp<ROMol, int>,
(python::arg("self"), python::arg("key"), python::arg("val"),
python::arg("computed") = false),
"Sets an integer valued molecular property\n\n"
" ARGUMENTS:\n"
" - key: the name of the property to be set (an unsigned "
"number).\n"
" - value: the property value as an integer.\n"
" - computed: (optional) marks the property as being "
"computed.\n"
" Defaults to False.\n\n")
.def("SetUnsignedProp", MolSetProp<ROMol, unsigned int>,
(python::arg("self"), python::arg("key"), python::arg("val"),
python::arg("computed") = false),
"Sets an unsigned integer valued molecular property\n\n"
" ARGUMENTS:\n"
" - key: the name of the property to be set (a string).\n"
" - value: the property value as an unsigned integer.\n"
" - computed: (optional) marks the property as being "
"computed.\n"
" Defaults to False.\n\n")
.def("SetBoolProp", MolSetProp<ROMol, bool>,
(python::arg("self"), python::arg("key"), python::arg("val"),
python::arg("computed") = false),
"Sets a boolean valued molecular property\n\n"
" ARGUMENTS:\n"
" - key: the name of the property to be set (a string).\n"
" - value: the property value as a bool.\n"
" - computed: (optional) marks the property as being "
"computed.\n"
" Defaults to False.\n\n")
.def("HasProp", MolHasProp<ROMol>, python::args("self", "key"),
"Queries a molecule to see if a particular property has been "
"assigned.\n\n"
" ARGUMENTS:\n"
" - key: the name of the property to check for (a string).\n")
.def(
"GetProp", GetPyProp<ROMol>,
(python::arg("self"), python::arg("key"),
python::arg("autoConvert") = false),
"Returns the value of the property.\n\n"
" ARGUMENTS:\n"
" - key: the name of the property to return (a string).\n\n"
" - autoConvert: if True attempt to convert the property into a python object\n\n"
" RETURNS: a string\n\n"
" NOTE:\n"
" - If the property has not been set, a KeyError exception "
"will be raised.\n")
.def("GetDoubleProp", GetProp<ROMol, double>,
python::args("self", "key"),
"Returns the double value of the property if possible.\n\n"
" ARGUMENTS:\n"
" - key: the name of the property to return (a string).\n\n"
" RETURNS: a double\n\n"
" NOTE:\n"
" - If the property has not been set, a KeyError exception "
"will be raised.\n")
.def("GetIntProp", GetProp<ROMol, int>, python::args("self", "key"),
"Returns the integer value of the property if possible.\n\n"
" ARGUMENTS:\n"
" - key: the name of the property to return (a string).\n\n"
" RETURNS: an integer\n\n"
" NOTE:\n"
" - If the property has not been set, a KeyError exception "
"will be raised.\n")
.def("GetUnsignedProp", GetProp<ROMol, unsigned int>,
python::args("self", "key"),
"Returns the unsigned int value of the property if possible.\n\n"
" ARGUMENTS:\n"
" - key: the name of the property to return (a string).\n\n"
" RETURNS: an unsigned integer\n\n"
" NOTE:\n"
" - If the property has not been set, a KeyError exception "
"will be raised.\n")
.def("GetBoolProp", GetProp<ROMol, bool>, python::args("self", "key"),
"Returns the Bool value of the property if possible.\n\n"
" ARGUMENTS:\n"
" - key: the name of the property to return (a string).\n\n"
" RETURNS: a bool\n\n"
" NOTE:\n"
" - If the property has not been set, a KeyError exception "
"will be raised.\n")
.def("ClearProp", MolClearProp<ROMol>, python::args("self", "key"),
"Removes a property from the molecule.\n\n"
" ARGUMENTS:\n"
" - key: the name of the property to clear (a string).\n")
.def("ClearComputedProps", MolClearComputedPropsHelper,
(python::arg("self"), python::arg("includeRings") = true),
"Removes all computed properties from the molecule.\n\n")
.def("UpdatePropertyCache", &ROMol::updatePropertyCache,
(python::arg("self"), python::arg("strict") = true),
"Regenerates computed properties like implicit valence and ring "
"information.\n\n")
.def("NeedsUpdatePropertyCache", &ROMol::needsUpdatePropertyCache,
(python::arg("self")),
"Returns true or false depending on whether implicit and "
"explicit "
"valence of the molecule have already been calculated.\n\n")
.def("GetStereoGroups", &ROMol::getStereoGroups,
"Returns a list of StereoGroups defining the relative "
"stereochemistry "
"of the atoms.\n",
python::return_internal_reference<
1, python::with_custodian_and_ward_postcall<0, 1>>(),
python::args("self"))
.def("GetPropNames", &ROMol::getPropList,
(python::arg("self"), python::arg("includePrivate") = false,
python::arg("includeComputed") = false),
"Returns a tuple with all property names for this molecule.\n\n"
" ARGUMENTS:\n"
" - includePrivate: (optional) toggles inclusion of private "
"properties in the result set.\n"
" Defaults to 0.\n"
" - includeComputed: (optional) toggles inclusion of computed "
"properties in the result set.\n"
" Defaults to 0.\n\n"
" RETURNS: a tuple of strings\n")
.def("GetPropsAsDict", GetPropsAsDict<ROMol>,
(python::arg("self"), python::arg("includePrivate") = false,
python::arg("includeComputed") = false,
python::arg("autoConvertStrings") = true),
"Returns a dictionary populated with the molecules properties.\n"
" n.b. Some properties are not able to be converted to python "
"types.\n\n"
" ARGUMENTS:\n"
" - includePrivate: (optional) toggles inclusion of private "
"properties in the result set.\n"
" Defaults to False.\n"
" - includeComputed: (optional) toggles inclusion of computed "
"properties in the result set.\n"
" Defaults to False.\n\n"
" RETURNS: a dictionary\n")
.def("GetAromaticAtoms", MolGetAromaticAtoms,
python::return_value_policy<
python::manage_new_object,
python::with_custodian_and_ward_postcall<0, 1>>(),
python::args("self"),
"Returns a read-only sequence containing all of the molecule's "
"aromatic Atoms.\n")
.def("GetAtomsMatchingQuery", MolGetQueryAtoms,
python::return_value_policy<
python::manage_new_object,
python::with_custodian_and_ward_postcall<0, 1>>(),
python::args("self", "qa"),
"Returns a read-only sequence containing all of the atoms in a "
"molecule that match the query atom.\n")
// enable pickle support
.def_pickle(mol_pickle_suite())
.def("Debug", MolDebug,
(python::arg("self"), python::arg("useStdout") = true),
"Prints debugging information about the molecule.\n")
.def("ToBinary", MolToBinary, python::args("self"),
"Returns a binary string representation of the molecule.\n")
.def("ToBinary", MolToBinaryWithProps,
(python::arg("self"), python::arg("propertyFlags")),
"Returns a binary string representation of the molecule pickling "
"the "
"specified properties.\n")
.def("GetRingInfo", &ROMol::getRingInfo,
python::return_value_policy<python::reference_existing_object>(),
python::args("self"),
"Returns the number of molecule's RingInfo object.\n\n");
python::register_ptr_to_python<std::shared_ptr<ROMol>>();
// ---------------------------------------------------------------------------------------------
python::def("_HasSubstructMatchStr", HasSubstructMatchStr,
(python::arg("pkl"), python::arg("query"),
python::arg("recursionPossible") = true,
python::arg("useChirality") = false,
python::arg("useQueryQueryMatches") = false),
"This function is included to speed substructure queries from "
"databases, \n"
"it's probably not of\n"
"general interest.\n\n"
" ARGUMENTS:\n"
" - pkl: a Molecule pickle\n\n"
" - query: a Molecule\n\n"
" - recursionPossible: (optional)\n\n"
" - useChirality: (optional)\n\n"
" - useQueryQueryMatches: use query-query matching logic\n\n"
" RETURNS: True or False\n");
python::class_<ReadWriteMol, python::bases<ROMol>>(
"RWMol", rwmolClassDoc.c_str(),
python::init<const ROMol &>(python::args("self", "m"),
"Construct from a Mol"))
.def(python::init<>(python::args("self")))
.def(python::init<const std::string &>(
python::args("self", "pklString")))
.def(python::init<const std::string &, unsigned int>(
(python::args("self", "pklString", "propertyFlags"))))
.def(python::init<const ROMol &, bool, int>(
(python::arg("self"), python::arg("mol"),
python::arg("quickCopy") = false, python::arg("confId") = -1)))
.def("__copy__", &generic__copy__<ReadWriteMol>, python::args("self"))
.def("__deepcopy__", &generic__deepcopy__<ReadWriteMol>,
python::args("self", "memo"))
.def("__enter__", &ReadWriteMol::enter,
python::return_internal_reference<>())
.def("__exit__", &ReadWriteMol::exit)
.def("RemoveAtom", &ReadWriteMol::RemoveAtom,
python::args("self", "idx"),
"Remove the specified atom from the molecule")
.def("RemoveBond", &ReadWriteMol::RemoveBond,
python::args("self", "idx1", "idx2"),
"Remove the specified bond from the molecule")
.def("AddBond", &ReadWriteMol::AddBond,
((python::arg("self"), python::arg("beginAtomIdx")),
python::arg("endAtomIdx"),
python::arg("order") = Bond::UNSPECIFIED),
"add a bond, returns the new number of bonds")
.def("AddAtom", &ReadWriteMol::AddAtom,
((python::arg("self"), python::arg("atom"))),
"add an atom, returns the index of the newly added atom")
.def("ReplaceAtom", &ReadWriteMol::ReplaceAtom,
((python::arg("self"), python::arg("index")),
python::arg("newAtom"), python::arg("updateLabel") = false,
python::arg("preserveProps") = false),
"replaces the specified atom with the provided one\n"
"If updateLabel is True, the new atom becomes the active atom\n"
"If preserveProps is True preserve keep the existing props unless "
"explicit set on the new atom")
.def("ReplaceBond", &ReadWriteMol::ReplaceBond,
((python::arg("self"), python::arg("index")),
python::arg("newBond"), python::arg("preserveProps") = false,
python::arg("keepSGroups") = true),
"replaces the specified bond with the provided one.\n"
"If preserveProps is True preserve keep the existing props unless "
"explicit set on the new bond. If keepSGroups is False, all"
"Substance Groups referencing the bond will be dropped.")
.def("GetMol", &ReadWriteMol::GetMol,
"Returns a Mol (a normal molecule)",
python::return_value_policy<python::manage_new_object>(),
python::args("self"))
.def("SetStereoGroups", &ReadWriteMol::SetStereoGroups,
((python::arg("self"), python::arg("stereo_groups"))),
"Set the stereo groups")
.def("InsertMol", &ReadWriteMol::insertMol,
((python::arg("self"), python::arg("mol"))),
"Insert (add) the given molecule into this one")
.def("BeginBatchEdit", &RWMol::beginBatchEdit, python::args("self"),
"starts batch editing")
.def("RollbackBatchEdit", &RWMol::rollbackBatchEdit,
python::args("self"), "cancels batch editing")
.def("CommitBatchEdit", &RWMol::commitBatchEdit, python::args("self"),
"finishes batch editing and makes the actual changes")
// enable pickle support
.def_pickle(mol_pickle_suite());
};
};
} // namespace RDKit
void wrap_mol() { RDKit::mol_wrapper::wrap(); }