Files
rdkit/Code/GraphMol/Wrap/MolOps.cpp
2010-11-22 04:12:00 +00:00

985 lines
33 KiB
C++
Executable File

// $Id$
//
// Copyright (C) 2003-2009 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 "rdmolops.h"
#include <boost/python.hpp>
#include <numpy/arrayobject.h>
#include <string>
#include <math.h>
#include <DataStructs/ExplicitBitVect.h>
#include <GraphMol/RDKitBase.h>
#include <GraphMol/RDKitQueries.h>
#include <GraphMol/Substruct/SubstructMatch.h>
#include <GraphMol/Subgraphs/Subgraphs.h>
#include <GraphMol/Fingerprints/Fingerprints.h>
#include <GraphMol/FileParsers/MolFileStereochem.h>
#include <GraphMol/ChemTransforms/ChemTransforms.h>
#include <RDBoost/Wrap.h>
namespace python = boost::python;
namespace RDKit{
ROMol *addHs(const ROMol &orig,bool explicitOnly=false,bool addCoords=false){
return MolOps::addHs(orig,explicitOnly,addCoords);
}
ROMol *removeHs(const ROMol &orig,bool implicitOnly=false){
return MolOps::removeHs(orig,implicitOnly);
}
int getSSSR(ROMol &mol) {
VECT_INT_VECT rings;
int nr = MolOps::findSSSR(mol, rings);
return nr;
}
PyObject* replaceSubstructures(const ROMol &orig,
const ROMol &query,
const ROMol &replacement,
bool replaceAll=false) {
std::vector<ROMOL_SPTR> v=replaceSubstructs(orig, query,
replacement, replaceAll);
PyObject *res=PyTuple_New(v.size());
for(unsigned int i=0;i<v.size();++i){
PyTuple_SetItem(res,i,
python::converter::shared_ptr_to_python(v[i]));
}
return res;
}
void addRecursiveQuery(ROMol &mol,
const ROMol &query,
unsigned int atomIdx,
bool preserveExistingQuery){
if(atomIdx>=mol.getNumAtoms()){
throw_value_error("atom index exceeds mol.GetNumAtoms()");
}
RecursiveStructureQuery *q = new RecursiveStructureQuery(new ROMol(query));
Atom *oAt=mol.getAtomWithIdx(atomIdx);
if(!oAt->hasQuery()){
QueryAtom qAt(*oAt);
static_cast<RWMol &>(mol).replaceAtom(atomIdx,&qAt);
oAt = mol.getAtomWithIdx(atomIdx);
}
if(!preserveExistingQuery){
// FIX: this leaks a query atom on oAt
oAt->setQuery(q);
} else {
oAt->expandQuery(q,Queries::COMPOSITE_AND);
}
}
void sanitizeMol(ROMol &mol) {
RWMol &wmol = static_cast<RWMol &>(mol);
MolOps::sanitizeMol(wmol);
}
RWMol *getEditable(const ROMol &mol) {
RWMol *res = static_cast<RWMol *>(new ROMol(mol,false));
return res;
}
ROMol *getNormal(const RWMol &mol) {
ROMol *res = static_cast<ROMol *>(new RWMol(mol));
return res;
}
void kekulizeMol(ROMol &mol,bool clearAromaticFlags=false) {
RWMol &wmol = static_cast<RWMol &>(mol);
MolOps::Kekulize(wmol,clearAromaticFlags);
}
void setAromaticityMol(ROMol &mol){
RWMol &wmol = static_cast<RWMol &>(mol);
MolOps::setAromaticity(wmol);
}
void setConjugationMol(ROMol &mol) {
RWMol &wmol = static_cast<RWMol &>(mol);
MolOps::setConjugation(wmol);
}
void assignRadicalsMol(ROMol &mol) {
RWMol &wmol = static_cast<RWMol &>(mol);
MolOps::assignRadicals(wmol);
}
void setHybridizationMol(ROMol &mol) {
RWMol &wmol = static_cast<RWMol &>(mol);
MolOps::setHybridization(wmol);
}
VECT_INT_VECT getSymmSSSR(ROMol &mol) {
VECT_INT_VECT rings;
MolOps::symmetrizeSSSR(mol, rings);
return rings;
}
PyObject *getDistanceMatrix(ROMol &mol, bool useBO=false,
bool useAtomWts=false,bool force=false,
const char *prefix=0) {
int nats = mol.getNumAtoms();
npy_intp dims[2];
dims[0] = nats;
dims[1] = nats;
double *distMat;
distMat = MolOps::getDistanceMat(mol, useBO, useAtomWts,force,prefix);
PyArrayObject *res = (PyArrayObject *)PyArray_SimpleNew(2,dims,NPY_DOUBLE);
memcpy(static_cast<void *>(res->data),
static_cast<void *>(distMat),nats*nats*sizeof(double));
return PyArray_Return(res);
}
PyObject *getAdjacencyMatrix(ROMol &mol, bool useBO=false,
int emptyVal=0,bool force=false,
const char *prefix=0) {
int nats = mol.getNumAtoms();
npy_intp dims[2];
dims[0] = nats;
dims[1] = nats;
double *tmpMat = MolOps::getAdjacencyMatrix(mol, useBO, emptyVal,force,prefix);
PyArrayObject *res;
if(useBO){
// if we're using valence, the results matrix is made up of doubles
res = (PyArrayObject *)PyArray_SimpleNew(2,dims,
NPY_DOUBLE);
memcpy(static_cast<void *>(res->data),
static_cast<void *>(tmpMat),nats*nats*sizeof(double));
} else {
res = (PyArrayObject *)PyArray_SimpleNew(2,dims,
NPY_INT);
int *data = (int *)res->data;
for(int i=0;i<nats;i++){
for(int j=0;j<nats;j++){
data[i*nats+j] = (int)round(tmpMat[i*nats+j]);
}
}
}
return PyArray_Return(res);
}
python::tuple GetMolFrags(const ROMol &mol,bool asMols){
python::list res;
if(!asMols){
VECT_INT_VECT frags;
MolOps::getMolFrags(mol,frags);
for(unsigned int i=0;i<frags.size();++i){
python::list tpl;
for(unsigned int j=0;j<frags[i].size();++j){
tpl.append(frags[i][j]);
}
res.append(python::tuple(tpl));
}
} else {
std::vector<boost::shared_ptr<ROMol> > frags;
frags=MolOps::getMolFrags(mol);
for(unsigned int i=0;i<frags.size();++i){
res.append(frags[i]);
}
}
return python::tuple(res);
}
ExplicitBitVect *wrapLayeredFingerprint(const ROMol &mol,unsigned int layerFlags,
unsigned int minPath,unsigned int maxPath,
unsigned int fpSize,
double tgtDensity,
unsigned int minSize,
python::list atomCounts,
ExplicitBitVect *includeOnlyBits,
bool branchedPaths){
std::vector<unsigned int> *atomCountsV=0;
if(atomCounts){
atomCountsV = new std::vector<unsigned int>;
unsigned int nAts=python::extract<unsigned int>(atomCounts.attr("__len__")());
if(nAts<mol.getNumAtoms()){
throw_value_error("atomCounts shorter than the number of atoms");
}
atomCountsV->resize(nAts);
for(unsigned int i=0;i<nAts;++i){
(*atomCountsV)[i] = python::extract<unsigned int>(atomCounts[i]);
}
}
ExplicitBitVect *res;
res = RDKit::LayeredFingerprintMol(mol,layerFlags,minPath,maxPath,fpSize,tgtDensity,minSize,atomCountsV,includeOnlyBits,branchedPaths);
if(atomCountsV){
for(unsigned int i=0;i<atomCountsV->size();++i){
atomCounts[i] = (*atomCountsV)[i];
}
delete atomCountsV;
}
return res;
}
python::object findAllSubgraphsOfLengthsMtoNHelper(const ROMol &mol, unsigned int lowerLen,
unsigned int upperLen, bool useHs=false){
if(lowerLen>upperLen){
throw_value_error("lowerLen > upperLen");
}
INT_PATH_LIST_MAP oMap=findAllSubgraphsOfLengthsMtoN(mol,lowerLen,upperLen,useHs);
python::list res;
for(unsigned int i=lowerLen;i<=upperLen;++i){
python::list tmp;
const PATH_LIST &pth=oMap[i];
for(PATH_LIST_CI pthit=pth.begin();pthit!=pth.end();++pthit){
tmp.append(python::tuple(*pthit));
}
res.append(tmp);
}
return python::tuple(res);
};
struct molops_wrapper {
static void wrap() {
std::string docString;
// ------------------------------------------------------------------------
docString="Kekulize, check valencies, set aromaticity, conjugation and hybridization\n\
\n\
- The molecule is modified in place.\n\
\n\
- If sanitization fails, an exception will be thrown\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to be modified\n\
\n\
NOTES:\n\
\n";
python::def("SanitizeMol", sanitizeMol,
docString.c_str());
// ------------------------------------------------------------------------
docString="Get the smallest set of simple rings for a molecule.\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use.\n\
\n\
RETURNS: the number of rings found\n\
This will be equal to NumBonds-NumAtoms+1 for single-fragment molecules.\n\
\n";
python::def("GetSSSR", getSSSR,
docString.c_str());
// ------------------------------------------------------------------------
docString="Get a symmetrized SSSR for a molecule.\n\
\n\
The symmetrized SSSR is at least as large as the SSSR for a molecule.\n\
In certain highly-symmetric cases (e.g. cubane), the symmetrized SSSR can be\n\
a bit larger (i.e. the number of symmetrized rings is >= NumBonds-NumAtoms+1).\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use.\n\
\n\
RETURNS: the number of rings found\n\
\n";
python::def("GetSymmSSSR", getSymmSSSR,
docString.c_str());
// ------------------------------------------------------------------------
docString="Adds hydrogens to the graph of a molecule.\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to be modified\n\
\n\
- explicitOnly: (optional) if this toggle is set, only explicit Hs will\n\
be added to the molecule. Default value is 0 (add implicit and explicit Hs).\n\
\n\
- addCoords: (optional) if this toggle is set, The Hs will have 3D coordinates\n\
set. Default value is 0 (no 3D coords).\n\
\n\
RETURNS: a new molecule with added Hs\n\
\n\
NOTES:\n\
\n\
- The original molecule is *not* modified.\n\
\n\
- Much of the code assumes that Hs are not included in the molecular\n\
topology, so be *very* careful with the molecule that comes back from\n\
this function.\n\
\n";
python::def("AddHs", addHs,
(python::arg("mol"),python::arg("explicitOnly")=false,
python::arg("addCoords")=false),
docString.c_str(),
python::return_value_policy<python::manage_new_object>());
// ------------------------------------------------------------------------
docString="Removes any hydrogens from the graph of a molecule.\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to be modified\n\
\n\
- implicitOnly: (optional) if this toggle is set, only implicit Hs will\n\
be removed from the graph. Default value is 0 (remove implicit and explicit Hs).\n\
\n\
RETURNS: a new molecule with the Hs removed\n\
\n\
NOTES:\n\
\n\
- The original molecule is *not* modified.\n\
\n";
python::def("RemoveHs", removeHs,
(python::arg("mol"),python::arg("implicitOnly")=false),
docString.c_str(),
python::return_value_policy<python::manage_new_object>());
python::def("MergeQueryHs", MolOps::mergeQueryHs,
(python::arg("mol")),
"merges hydrogens into their neighboring atoms as queries",
python::return_value_policy<python::manage_new_object>());
// ------------------------------------------------------------------------
docString="Removes atoms matching a substructure query from a molecule\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to be modified\n\
\n\
- query: the molecule to be used as a substructure query\n\
\n\
- onlyFrags: (optional) if this toggle is set, atoms will only be removed if\n\
the entire fragment in which they are found is matched by the query.\n\
See below for examples.\n\
Default value is 0 (remove the atoms whether or not the entire fragment matches)\n\
\n\
RETURNS: a new molecule with the substructure removed\n\
\n\
NOTES:\n\
\n\
- The original molecule is *not* modified.\n\
\n\
EXAMPLES:\n\
\n\
The following examples substitute SMILES/SMARTS strings for molecules, you'd have\n\
to actually use molecules:\n\
\n\
- DeleteSubstructs('CCOC','OC') -> 'CC'\n\
\n\
- DeleteSubstructs('CCOC','OC',1) -> 'CCOC'\n\
\n\
- DeleteSubstructs('CCOCCl.Cl','Cl',1) -> 'CCOCCl'\n\
\n\
- DeleteSubstructs('CCOCCl.Cl','Cl') -> 'CCOC'\n\
\n";
python::def("DeleteSubstructs", deleteSubstructs,
(python::arg("mol"),python::arg("query"),
python::arg("onlyFrags")=false),
docString.c_str(),
python::return_value_policy<python::manage_new_object>());
// ------------------------------------------------------------------------
docString="Replaces atoms matching a substructure query in a molecule\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to be modified\n\
\n\
- query: the molecule to be used as a substructure query\n\
\n\
- replacement: the molecule to be used as the replacement\n\
\n\
- replaceAll: (optional) if this toggle is set, all substructures matching\n\
the query will be replaced in a single result, otherwise each result will\n\
contain a separate replacement.\n\
Default value is False (return multiple replacements)\n\
\n\
RETURNS: a tuple of new molecules with the substructures replaced removed\n\
\n\
NOTES:\n\
\n\
- The original molecule is *not* modified.\n\
\n\
EXAMPLES:\n\
\n\
The following examples substitute SMILES/SMARTS strings for molecules, you'd have\n\
to actually use molecules:\n\
\n\
- ReplaceSubstructs('CCOC','OC','NC') -> ('CCNC',)\n\
\n\
- ReplaceSubstructs('COCCOC','OC','NC') -> ('COCCNC','CNCCOC')\n\
\n\
- ReplaceSubstructs('COCCOC','OC','NC',True) -> ('CNCCNC',)\n\
\n";
python::def("ReplaceSubstructs", replaceSubstructures,
(python::arg("mol"),python::arg("query"),
python::arg("replacement"),
python::arg("replaceAll")=false),
docString.c_str());
// ------------------------------------------------------------------------
docString="Returns the molecule's topological distance matrix.\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
\n\
- useBO: (optional) toggles use of bond orders in calculating the distance matrix.\n\
Default value is 0.\n\
\n\
- useAtomWts: (optional) toggles using atom weights for the diagonal elements of the\n\
matrix (to return a \"Balaban\" distance matrix).\n\
Default value is 0.\n\
\n\
- force: (optional) forces the calculation to proceed, even if there is a cached value.\n\
Default value is 0.\n\
\n\
- prefix: (optional, internal use) sets the prefix used in the property cache\n\
Default value is "".\n\
\n\
RETURNS: a Numeric array of floats with the distance matrix\n\
\n";
python::def("GetDistanceMatrix", getDistanceMatrix,
(python::arg("mol"),python::arg("useBO")=false,
python::arg("useAtomWts")=false,
python::arg("force")=false,
python::arg("prefix")=""),
docString.c_str());
// ------------------------------------------------------------------------
docString="Returns the molecule's adjacency matrix.\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
\n\
- useBO: (optional) toggles use of bond orders in calculating the matrix.\n\
Default value is 0.\n\
\n\
- emptyVal: (optional) sets the elements of the matrix between non-adjacent atoms\n\
Default value is 0.\n\
\n\
- force: (optional) forces the calculation to proceed, even if there is a cached value.\n\
Default value is 0.\n\
\n\
- prefix: (optional, internal use) sets the prefix used in the property cache\n\
Default value is "".\n\
\n\
RETURNS: a Numeric array of floats containing the adjacency matrix\n\
\n";
python::def("GetAdjacencyMatrix", getAdjacencyMatrix,
(python::arg("mol"), python::arg("useBO")=false,
python::arg("emptyVal")=0,
python::arg("force")=false,
python::arg("prefix")=""),
docString.c_str());
// ------------------------------------------------------------------------
docString="Kekulizes the molecule\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
\n\
- clearAromaticFlags: (optional) if this toggle is set, all atoms and bonds in the \n\
molecule will be marked non-aromatic following the kekulization.\n\
Default value is 0.\n\
\n\
NOTES:\n\
\n\
- The molecule is modified in place.\n\
\n";
python::def("Kekulize", kekulizeMol,
(python::arg("mol"),python::arg("clearAromaticFlags")=false),
docString.c_str());
// ------------------------------------------------------------------------
docString="does aromaticity perception\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
\n\
NOTES:\n\
\n\
- The molecule is modified in place.\n\
\n";
python::def("SetAromaticity", setAromaticityMol,
(python::arg("mol")),
docString.c_str());
docString="finds conjugated bonds\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
\n\
NOTES:\n\
\n\
- The molecule is modified in place.\n\
\n";
python::def("SetConjugation", setConjugationMol,
(python::arg("mol")),
docString.c_str());
docString="Assigns hybridization states to atoms\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
\n\
NOTES:\n\
\n\
- The molecule is modified in place.\n\
\n";
python::def("SetHybridization", setHybridizationMol,
(python::arg("mol")),
docString.c_str());
docString="Assigns radical counts to atoms\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
\n\
NOTES:\n\
\n\
- The molecule is modified in place.\n\
\n";
python::def("AssignRadicals", assignRadicalsMol,
(python::arg("mol")),
docString.c_str());
// ------------------------------------------------------------------------
docString="Finds all subgraphs of a particular length in a molecule\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
\n\
- length: an integer with the target number of bonds for the subgraphs.\n\
\n\
- useHs: (optional) toggles whether or not bonds to Hs that are part of the graph\n\
should be included in the results.\n\
Defaults to 0.\n\
\n\
- verbose: (optional, internal use) toggles verbosity in the search algorithm.\n\
Defaults to 0.\n\
\n\
RETURNS: a tuple of 2-tuples with bond IDs\n\
\n\
NOTES: \n\
\n\
- Difference between _subgraphs_ and _paths_ :: \n\
\n\
Subgraphs are potentially branched, whereas paths (in our \n\
terminology at least) cannot be. So, the following graph: \n\
\n\
C--0--C--1--C--3--C\n\
|\n\
2\n\
|\n\
C\n\
has 3 _subgraphs_ of length 3: (0,1,2),(0,1,3),(2,1,3)\n\
but only 2 _paths_ of length 3: (0,1,3),(2,1,3)\n\
\n";
python::def("FindAllSubgraphsOfLengthN", &findAllSubgraphsOfLengthN,
(python::arg("mol"),python::arg("length"),
python::arg("useHs")=false),
docString.c_str());
// ------------------------------------------------------------------------
docString="Finds all subgraphs of a particular length in a molecule\n\
See documentation for FindAllSubgraphsOfLengthN for definitions\n\
\n";
python::def("FindAllSubgraphsOfLengthMToN", &findAllSubgraphsOfLengthsMtoNHelper,
(python::arg("mol"),python::arg("min"),python::arg("max"),
python::arg("useHs")=false),
docString.c_str());
// ------------------------------------------------------------------------
docString="Finds unique subgraphs of a particular length in a molecule\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
\n\
- length: an integer with the target number of bonds for the subgraphs.\n\
\n\
- useHs: (optional) toggles whether or not bonds to Hs that are part of the graph\n\
should be included in the results.\n\
Defaults to 0.\n\
\n\
- useBO: (optional) Toggles use of bond orders in distinguishing one subgraph from\n\
another.\n\
Defaults to 1.\n\
\n\
RETURNS: a tuple of tuples with bond IDs\n\
\n\
\n";
python::def("FindUniqueSubgraphsOfLengthN", &findUniqueSubgraphsOfLengthN,
(python::arg("mol"),python::arg("length"),
python::arg("useHs")=false,python::arg("useBO")=true),
docString.c_str());
// ------------------------------------------------------------------------
docString="Finds all paths of a particular length in a molecule\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
\n\
- length: an integer with the target length for the paths.\n\
\n\
- useBonds: (optional) toggles the use of bond indices in the paths.\n\
Otherwise atom indices are used. *Note* this behavior is different\n\
from that for subgraphs.\n\
Defaults to 1.\n\
\n\
RETURNS: a tuple of tuples with IDs for the bonds.\n\
\n\
NOTES: \n\
\n\
- Difference between _subgraphs_ and _paths_ :: \n\
\n\
Subgraphs are potentially branched, whereas paths (in our \n\
terminology at least) cannot be. So, the following graph: \n\
\n\
C--0--C--1--C--3--C\n\
|\n\
2\n\
|\n\
C\n\
\n\
has 3 _subgraphs_ of length 3: (0,1,2),(0,1,3),(2,1,3)\n\
but only 2 _paths_ of length 3: (0,1,3),(2,1,3)\n\
\n";
python::def("FindAllPathsOfLengthN", &findAllPathsOfLengthN,
(python::arg("mol"),python::arg("length"),
python::arg("useBonds")=true,python::arg("useHs")=false),
docString.c_str());
// ------------------------------------------------------------------------
docString="Finds the disconnected fragments from a molecule.\n\
\n\
For example, for the molecule 'CC(=O)[O-].[NH3+]C' GetMolFrags() returns\n\
((0, 1, 2, 3), (4, 5))\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
- asMols: (optional) if this is provided and true, the fragments\n\
will be returned as molecules instead of atom ids.\n\
\n\
RETURNS: a tuple of tuples with IDs for the atoms in each fragment\n\
or a tuple of molecules.\n\
\n";
python::def("GetMolFrags", &GetMolFrags,
(python::arg("mol"),python::arg("asMols")=false),
docString.c_str());
// ------------------------------------------------------------------------
docString="Returns the formal charge for the molecule.\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
\n";
python::def("GetFormalCharge", &MolOps::getFormalCharge,docString.c_str());
// ------------------------------------------------------------------------
docString="Does the CIP stereochemistry assignment \n\
for the molecule's atoms (R/S) and double bond (Z/E).\n\
Chiral atoms will have a property '_CIPCode' indicating\n\
their chiral code.\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
- cleanIt: (optional) if provided, atoms with a chiral specifier that aren't\n\
actually chiral (e.g. atoms with duplicate substituents or only 2 substituents,\n\
etc.) will have their chiral code set to CHI_UNSPECIFIED\n\
- force: (optional) causes the calculation to be repeated, even if it has already\n\
been done\n\
\n";
python::def("AssignStereochemistry", MolOps::assignStereochemistry,
(python::arg("mol"),python::arg("cleanIt")=false,python::arg("force")=false),
docString.c_str());
// ------------------------------------------------------------------------
docString="Removes all stereochemistry info from the molecule.\n\
\n";
python::def("RemoveStereochemistry", MolOps::removeStereochemistry,
(python::arg("mol")),
docString.c_str());
// ------------------------------------------------------------------------
docString="Sets the chiral tags on a molecule's atoms based on \n\
a 3D conformation.\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
- confId: the conformer id to use, -1 for the default \n\
- replaceExistingTags: if True, existing stereochemistry information will be cleared \n\
before running the calculation. \n\
\n";
python::def("AssignAtomChiralTagsFromStructure", MolOps::assignChiralTypesFrom3D,
(python::arg("mol"),python::arg("confId")=-1,python::arg("replaceExistingTags")=true),
docString.c_str());
// ------------------------------------------------------------------------
docString="Returns an RDKit topological fingerprint for a molecule\n\
\n\
Explanation of the algorithm below.\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
\n\
- minPath: (optional) minimum number of bonds to include in the subgraphs\n\
Defaults to 1.\n\
\n\
- maxPath: (optional) maximum number of bonds to include in the subgraphs\n\
Defaults to 7.\n\
\n\
- fpSize: (optional) number of bits in the fingerprint\n\
Defaults to 2048.\n\
\n\
- nBitsPerHash: (optional) number of bits to set per path\n\
Defaults to 4.\n\
\n\
- useHs: (optional) include paths involving Hs in the fingerprint if the molecule\n\
has explicit Hs.\n\
Defaults to 1.\n\
\n\
- tgtDensity: (optional) fold the fingerprint until this minimum density has\n\
been reached\n\
Defaults to 0.\n\
\n\
- minSize: (optional) the minimum size the fingerprint will be folded to when\n\
trying to reach tgtDensity\n\
Defaults to 128.\n\
\n\
RETURNS: a DataStructs.ExplicitBitVect with _fpSize_ bits\n\
\n\
ALGORITHM:\n\
\n\
This algorithm functions by find all paths between minPath and maxPath in\n \
length. For each path:\n\
\n\
1) A hash is calculated.\n\
\n\
2) The hash is used to seed a random-number generator\n\
\n\
3) _nBitsPerHash_ random numbers are generated and used to set the corresponding\n\
bits in the fingerprint\n\
\n\
\n";
python::def("RDKFingerprint", RDKFingerprintMol,
(python::arg("mol"),python::arg("minPath")=1,
python::arg("maxPath")=7,python::arg("fpSize")=2048,
python::arg("nBitsPerHash")=4,python::arg("useHs")=true,
python::arg("tgtDensity")=0.0,python::arg("minSize")=128,
python::arg("branchedPaths")=true),
docString.c_str(),python::return_value_policy<python::manage_new_object>());
python::scope().attr("_RDKFingerprint_version")=RDKit::RDKFingerprintMolVersion;
// ------------------------------------------------------------------------
docString="Returns a layered fingerprint for a molecule\n\
\n\
NOTE: This function is experimental. The API or results may change from\n\
release to release.\n\
\n\
Explanation of the algorithm below.\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to use\n\
\n\
- layerFlags: (optional) which layers to include in the fingerprint\n\
See below for definitions. Defaults to all.\n\
\n\
- minPath: (optional) minimum number of bonds to include in the subgraphs\n\
Defaults to 1.\n\
\n\
- maxPath: (optional) maximum number of bonds to include in the subgraphs\n\
Defaults to 7.\n\
\n\
- fpSize: (optional) number of bits in the fingerprint\n\
Defaults to 2048.\n\
\n\
- tgtDensity: (optional) fold the fingerprint until this minimum density has\n\
been reached\n\
Defaults to 0.\n\
\n\
- minSize: (optional) the minimum size the fingerprint will be folded to when\n\
trying to reach tgtDensity\n\
Defaults to 128.\n\
\n\
- atomCounts: (optional) \n\
if provided, this should be a list at least as long as the number of atoms\n\
in the molecule. It will be used to provide the count of the number \n \
of paths that set bits each atom is involved in.\n\
NOTE: the list is not zeroed out here.\n\
\n\
- setOnlyBits: (optional) \n\
if provided, only bits that are set in this bit vector will be set\n\
in the result. This is essentially the same as doing:\n\
res &= setOnlyBits\n\
but also has an impact on the atomCounts (if being used)\n\
\n\
RETURNS: a DataStructs.ExplicitBitVect with _fpSize_ bits\n\
\n\
Layer definitions:\n\
- 0x01: pure topology\n\
- 0x02: bond order\n\
- 0x04: atom types\n\
- 0x08: presence of rings\n\
- 0x10: ring sizes\n\
- 0x20: aromaticity\n\
\n\
\n";
python::def("LayeredFingerprint", wrapLayeredFingerprint,
(python::arg("mol"),
python::arg("layerFlags")=0xFFFFFFFF,
python::arg("minPath")=1,
python::arg("maxPath")=7,python::arg("fpSize")=2048,
python::arg("tgtDensity")=0.0,python::arg("minSize")=128,
python::arg("atomCounts")=python::list(),
python::arg("setOnlyBits")=(ExplicitBitVect *)0,
python::arg("branchedPaths")=true),
docString.c_str(),python::return_value_policy<python::manage_new_object>());
python::scope().attr("_LayeredFingerprint_version")=RDKit::LayeredFingerprintMolVersion;
python::scope().attr("LayeredFingerprint_substructLayers")=RDKit::substructLayers;
docString="Set the wedging on single bonds in a molecule.\n \
The wedging scheme used is that from Mol files.\n \
\n\
ARGUMENTS:\n\
\n\
- molecule: the molecule to update\n \
\n\
\n";
python::def("WedgeMolBonds", WedgeMolBonds,
docString.c_str());
// ------------------------------------------------------------------------
docString="Replaces sidechains in a molecule with dummy atoms for their attachment points.\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to be modified\n\
\n\
- coreQuery: the molecule to be used as a substructure query for recognizing the core\n\
\n\
RETURNS: a new molecule with the sidechains removed\n\
\n\
NOTES:\n\
\n\
- The original molecule is *not* modified.\n\
\n\
EXAMPLES:\n\
\n\
The following examples substitute SMILES/SMARTS strings for molecules, you'd have\n\
to actually use molecules:\n\
\n\
- ReplaceSidechains('CCC1CCC1','C1CCC1') -> '[Xa]C1CCC1'\n\
\n\
- ReplaceSidechains('CCC1CC1','C1CCC1') -> ''\n\
\n\
- ReplaceSidechains('C1CC2C1CCC2','C1CCC1') -> '[Xa]C1CCC1[Xb]'\n\
\n";
python::def("ReplaceSidechains", replaceSidechains,
(python::arg("mol"),python::arg("coreQuery")),
docString.c_str(),
python::return_value_policy<python::manage_new_object>());
// ------------------------------------------------------------------------
docString="Removes the core of a molecule and labels the sidechains with dummy atoms.\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to be modified\n\
\n\
- coreQuery: the molecule to be used as a substructure query for recognizing the core\n\
\n\
- replaceDummies: toggles replacement of atoms that match dummies in the query\n\
\n\
RETURNS: a new molecule with the core removed\n\
\n\
NOTES:\n\
\n\
- The original molecule is *not* modified.\n\
\n\
EXAMPLES:\n\
\n\
The following examples substitute SMILES/SMARTS strings for molecules, you'd have\n\
to actually use molecules:\n\
\n\
- ReplaceCore('CCC1CCC1','C1CCC1') -> 'CC[Xa]'\n\
\n\
- ReplaceCore('CCC1CC1','C1CCC1') -> ''\n\
\n\
- ReplaceCore('C1CC2C1CCC2','C1CCC1') -> '[Xa]C1CCC1[Xb]'\n\
\n\
- ReplaceCore('C1CNCC1','N') -> '[Xa]CCCC[Xb]'\n\
\n\
- ReplaceCore('C1CCC1CN','C1CCC1[*]',False) -> '[Xa]CN'\n\
\n";
python::def("ReplaceCore", replaceCore,
(python::arg("mol"),python::arg("coreQuery"),
python::arg("replaceDummies")=true,
python::arg("labelByIndex")=false),
docString.c_str(),
python::return_value_policy<python::manage_new_object>());
// ------------------------------------------------------------------------
docString="Adds a recursive query to an atom\n\
\n\
ARGUMENTS:\n\
\n\
- mol: the molecule to be modified\n\
\n\
- query: the molecule to be used as the recursive query (this will be copied)\n\
\n\
- atomIdx: the atom to modify\n\
\n\
- preserveExistingQuery: (optional) if this is set, existing query information on the atom will be preserved\n\
\n\
RETURNS: None\n\
\n";
python::def("AddRecursiveQuery", addRecursiveQuery,
(python::arg("mol"),python::arg("query"),
python::arg("atomIdx"),python::arg("preserveExistingQuery")=true),
docString.c_str());
};
};
}
void wrap_molops() {
RDKit::molops_wrapper::wrap();
}