// $Id$ // // Copyright (C) 2005-2007 Rational Discovery LLC // // @@ All Rights Reserved @@ // #include "GridUtils.h" #include "Grid3D.h" #include "UniformGrid3D.h" #include "point.h" #include #include #include using namespace RDKit; namespace RDGeom { template double tanimotoDistance(const GRIDTYPE &grid1, const GRIDTYPE &grid2) { if (!grid1.compareParams(grid2)) { throw ValueErrorException("Grid parameters do not match"); } const DiscreteValueVect *v1 = grid1.getOccupancyVect(); const DiscreteValueVect *v2 = grid2.getOccupancyVect(); unsigned int dist = computeL1Norm(*v1, *v2); unsigned int totv1 = v1->getTotalVal(); unsigned int totv2 = v2->getTotalVal(); double inter = 0.5*(totv1 + totv2 - dist); double res = dist/(dist + inter); return res; } template double tanimotoDistance(const UniformGrid3D &grid1, const UniformGrid3D &grid2); template double protrudeDistance(const GRIDTYPE &grid1, const GRIDTYPE &grid2) { if (!grid1.compareParams(grid2)) { throw ValueErrorException("Grid parameters do not match"); } const DiscreteValueVect *v1 = grid1.getOccupancyVect(); const DiscreteValueVect *v2 = grid2.getOccupancyVect(); unsigned int totv1 = v1->getTotalVal(); unsigned int totv2 = v2->getTotalVal(); unsigned int totProtrude = computeL1Norm(*v1, *v2); unsigned int intersectVolume = (totv1+totv2-totProtrude)/2; double res = (1.0*totv1-intersectVolume)/(1.0*totv1); return res; } template double protrudeDistance(const UniformGrid3D &grid1, const UniformGrid3D &grid2); std::map< int, std::vector > gridIdxCache; std::vector computeGridIndices(const UniformGrid3D &grid,double windowRadius){ double gridSpacing=grid.getSpacing(); int radInGrid=static_cast(ceil(windowRadius/gridSpacing)); //if(gridIdxCache.count(radInGrid)>0){ // return gridIdxCache[radInGrid]; //} unsigned int dX,dY,dZ; dX = grid.getNumX(); dY = grid.getNumY(); dZ = grid.getNumZ(); std::vector res; for(int i=-radInGrid;i<=radInGrid;++i){ for(int j=-radInGrid;j<=radInGrid;++j){ for(int k=-radInGrid;k<=radInGrid;++k){ double r2=i*i+j*j+k*k; int d=static_cast(sqrt(r2)); if(d<=radInGrid){ res.push_back((i*dY+j)*dX+k); } } } } gridIdxCache[radInGrid]=res; return res; } Point3D computeGridCentroid(const UniformGrid3D &grid, const Point3D &pt, double windowRadius, double &weightSum){ weightSum = 0.0; const DiscreteValueVect *v1 = grid.getOccupancyVect(); Point3D centroid(0.0,0.0,0.0); unsigned int idxI = grid.getGridPointIndex(pt); std::vector indicesInSphere=computeGridIndices(grid,windowRadius); for(std::vector::const_iterator it=indicesInSphere.begin(); it!=indicesInSphere.end();++it){ int idx=idxI+*it; if(idx>=0 && static_cast(idx)getLength()){ unsigned int wt=v1->getVal(idx); centroid += grid.getGridPointLoc(static_cast(idx))*wt; weightSum += wt; } } return centroid/weightSum; } std::vector findGridTerminalPoints(const UniformGrid3D &grid, double windowRadius, double inclusionFraction){ std::vector res; std::vector indicesInSphere=computeGridIndices(grid,windowRadius); const DiscreteValueVect *storage=grid.getOccupancyVect(); unsigned int maxGridVal = (0x1<getNumBitsPerVal())-1; for(unsigned int i=0;igetLength();++i){ if(storage->getVal(i)::const_iterator it=indicesInSphere.begin(); it!=indicesInSphere.end();++it){ int idx=i+*it; if(idx>=0 && static_cast(idx)getLength()){ volInSphere += storage->getVal(static_cast(idx)); ++nPtsHere; } } // ----- // the shape may be cut off by the edge of the grid, so // the actual max volume in the sphere may well be less // than the theoretical max: double maxPossValInSphere=nPtsHere*maxGridVal; if(volInSphere/maxPossValInSphere <= inclusionFraction){ Point3D ptI=grid.getGridPointLoc(i); double weightSum; Point3D centroid=computeGridCentroid(grid,ptI,windowRadius,weightSum); res.push_back(centroid); } } return res; } }