// 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 #include #include "props.hpp" #include "rdchem.h" #include "seqs.hpp" #include "substructmethods.h" // ours #include #include #include #include #include #include #include #include #include #include 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 &match) { return python::extract(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 groups; pythonObjectToVect(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 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( &rdExceptionTranslator); python::enum_( "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_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_( "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_( "Mol", molClassDoc.c_str(), python::init<>(python::args("self"), "Constructor, takes no arguments")) .def(python::init( python::args("self", "pklString"))) .def(python::init( (python::args("self", "pklString", "propertyFlags")))) .def(python::init( (python::arg("self"), python::arg("mol"), python::arg("quickCopy") = false, python::arg("confId") = -1))) .def("__copy__", &generic__copy__, python::args("self")) .def("__deepcopy__", &generic__deepcopy__, 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 ¶ms)) 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, (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, (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, (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, (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, (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, 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, (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, 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, 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, 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, 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, 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, (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::args("self"), "Returns the number of molecule's RingInfo object.\n\n"); python::register_ptr_to_python>(); // --------------------------------------------------------------------------------------------- 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_>( "RWMol", rwmolClassDoc.c_str(), python::init(python::args("self", "m"), "Construct from a Mol")) .def(python::init<>(python::args("self"))) .def(python::init( python::args("self", "pklString"))) .def(python::init( (python::args("self", "pklString", "propertyFlags")))) .def(python::init( (python::arg("self"), python::arg("mol"), python::arg("quickCopy") = false, python::arg("confId") = -1))) .def("__copy__", &generic__copy__, python::args("self")) .def("__deepcopy__", &generic__deepcopy__, 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::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(); }