// $Id$ // // Copyright (C) 2004-2008 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. // #include #define PY_ARRAY_UNIQUE_SYMBOL DistGeom_array_API #include "numpy/arrayobject.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace python = boost::python; namespace RDKit { bool doTriangleSmoothing(python::object boundsMatArg,double tol){ PyObject *boundsMatObj = boundsMatArg.ptr(); if(!PyArray_Check(boundsMatObj)) throw_value_error("Argument isn't an array"); PyArrayObject *boundsMat=reinterpret_cast(boundsMatObj); // get the dimensions of the array int nrows = boundsMat->dimensions[0]; int ncols = boundsMat->dimensions[1]; if(nrows!=ncols) throw_value_error("The array has to be square"); if(nrows<=0) throw_value_error("The array has to have a nonzero size"); if (boundsMat->descr->type_num != PyArray_DOUBLE) throw_value_error("Only double arrays are currently supported"); unsigned int dSize = nrows*nrows; double *cData = new double[dSize]; double *inData = reinterpret_cast(boundsMat->data); memcpy(static_cast(cData), static_cast(inData), dSize*sizeof(double)); DistGeom::BoundsMatrix::DATA_SPTR sdata(cData); DistGeom::BoundsMatrix bm(nrows,sdata); bool res=DistGeom::triangleSmoothBounds(&bm,tol); memcpy(static_cast(inData), static_cast(cData), dSize*sizeof(double)); return res; } PyObject *embedBoundsMatrix(python::object boundsMatArg,int maxIters=10, bool randomizeOnFailure=false,int numZeroFail=2, python::list weights=python::list(), int randomSeed=-1){ PyObject *boundsMatObj = boundsMatArg.ptr(); if(!PyArray_Check(boundsMatObj)) throw_value_error("Argument isn't an array"); PyArrayObject *boundsMat=reinterpret_cast(boundsMatObj); // get the dimensions of the array unsigned int nrows = boundsMat->dimensions[0]; unsigned int ncols = boundsMat->dimensions[1]; if(nrows!=ncols) throw_value_error("The array has to be square"); if(nrows<=0) throw_value_error("The array has to have a nonzero size"); if (boundsMat->descr->type_num != PyArray_DOUBLE) throw_value_error("Only double arrays are currently supported"); unsigned int dSize = nrows*nrows; double *cData = new double[dSize]; double *inData = reinterpret_cast(boundsMat->data); memcpy(static_cast(cData), static_cast(inData), dSize*sizeof(double)); DistGeom::BoundsMatrix::DATA_SPTR sdata(cData); DistGeom::BoundsMatrix bm(nrows,sdata); RDGeom::Point3D *positions=new RDGeom::Point3D[nrows]; std::vector posPtrs; for (unsigned int i = 0; i < nrows; i++) { posPtrs.push_back(&positions[i]); } RDNumeric::DoubleSymmMatrix distMat(nrows, 0.0); // ---- ---- ---- ---- ---- ---- ---- ---- ---- // start the embedding: bool gotCoords=false; for(int iter=0;iter=0) randomSeed+=iter*999; } if(gotCoords){ std::map,double> weightMap; unsigned int nElems=PySequence_Size(weights.ptr()); for(unsigned int entryIdx=0;entryIdxinitialize(); if(field->calcEnergy()>1e-5){ int needMore=1; while(needMore){ needMore=field->minimize(); } } delete field; } else { throw_value_error("could not embed matrix"); } // ---- ---- ---- ---- ---- ---- ---- ---- ---- // construct the results matrix: npy_intp dims[2]; dims[0] = nrows; dims[1] = 3; PyArrayObject *res = (PyArrayObject *)PyArray_SimpleNew(2,dims,NPY_DOUBLE); double *resData=reinterpret_cast(res->data); for(unsigned int i=0;i(&translate_value_error); std::string docString; docString = "Do triangle smoothing on a bounds matrix\n\n\ \n\ ARGUMENTS:\n\n\ - mat: a square Numeric array of doubles containing the bounds matrix, this matrix\n\ *is* modified by the smoothing\n\ \n\ RETURNS:\n\n\ a boolean indicating whether or not the smoothing worked.\n\ \n"; python::def("DoTriangleSmoothing", RDKit::doTriangleSmoothing, (python::arg("boundsMatrix"),python::arg("tol")=0.), docString.c_str()); docString = "Embed a bounds matrix and return the coordinates\n\n\ \n\ ARGUMENTS:\n\n\ - boundsMatrix: a square Numeric array of doubles containing the bounds matrix, this matrix\n\ should already be smoothed\n\ - maxIters: (optional) the maximum number of random distance matrices to try\n\ - randomizeOnFailure: (optional) toggles using random coords if a matrix fails to embed\n\ - numZeroFail: (optional) sets the number of zero eigenvalues to be considered a failure\n\ - weights: (optional) a sequence of 3 sequences (i,j,weight) indicating elements of \n\ the bounds matrix whose weights should be adjusted\n\ - randomSeed: (optional) sets the random number seed used for embedding\n\ \n\ RETURNS:\n\n\ a Numeric array of doubles with the coordinates\n\ \n"; python::def("EmbedBoundsMatrix", RDKit::embedBoundsMatrix, (python::arg("boundsMatrix"),python::arg("maxIters")=10, python::arg("randomizeOnFailure")=false, python::arg("numZeroFail")=2, python::arg("weights")=python::list(), python::arg("randomSeed")=-1), docString.c_str()); }