mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-03 21:44:30 +08:00
big step in moving away from siMath; add more tests
This commit is contained in:
@@ -9,7 +9,7 @@ rdkit_library(Shape
|
||||
siMath.cpp
|
||||
shape.cpp
|
||||
SHARED
|
||||
LINK_LIBRARIES GraphMol RDGeneral RDGeometryLib DataStructs Shape FileParsers RDGeneral RDGeometryLib RDBoost)
|
||||
LINK_LIBRARIES GraphMol RDGeneral RDGeometryLib DataStructs Shape Alignment EigenSolvers FileParsers RDGeneral RDGeometryLib RDBoost)
|
||||
|
||||
rdkit_headers(alignmentInfo.h
|
||||
atomGaussian.h
|
||||
|
||||
@@ -22,11 +22,32 @@ class TestCase(unittest.TestCase) :
|
||||
score = rdkit.Chem.rdShape.Align(mol1, mol2, maxIter=10)
|
||||
self.failUnlessAlmostEqual(score,1.0,1)
|
||||
|
||||
df1 = [x.strip().split('\t') for x in file(d1).readlines()]
|
||||
taniCol = df1[0].index('Shape-it::Tanimoto')
|
||||
|
||||
supp = Chem.SDMolSupplier(f2)
|
||||
t1=time.time()
|
||||
tanimoto = [rdkit.Chem.rdShape.Align(mol1, m, maxIter=0) for m in supp]
|
||||
t2=time.time()
|
||||
print "Alignment time: %.2f"%(t2-t1)
|
||||
#t1=time.time()
|
||||
#tanimoto = [rdkit.Chem.rdShape.Align(mol1, m, maxIter=0) for m in supp]
|
||||
#t2=time.time()
|
||||
#print "Alignment time: %.2f"%(t2-t1)
|
||||
tanimoto=[]
|
||||
outf = file('/tmp/compare.csv','w+')
|
||||
w = Chem.SDWriter('/tmp/shapeout.sdf')
|
||||
print >>outf,"idx,score1,score2,d,pct"
|
||||
for i,m in enumerate(supp):
|
||||
print '\n\n\n----------------------'
|
||||
print i
|
||||
tani = rdkit.Chem.rdShape.Align(mol1, m, maxIter=0)
|
||||
tanimoto.append(tani)
|
||||
d = float(df1[i+1][taniCol])-tani
|
||||
pct = abs(d)/tani
|
||||
print >>outf,'%d,%.4f,%.4f,%.4f,%.4f'%(i,float(df1[i+1][taniCol]),tani,d,pct)
|
||||
if d>0.25: print "%f %f %f"%(float(df1[i+1][taniCol]),tani,pct)
|
||||
#self.failUnless(abs(d)<0.25,"%f %f %f"%(float(df1[i+1][taniCol]),tani,pct))
|
||||
if pct>0.25: print "%f %f %f"%(float(df1[i+1][taniCol]),tani,pct)
|
||||
#self.failUnless(pct<0.5,"%f %f %f"%(float(df1[i+1][taniCol]),tani,pct))
|
||||
m.SetProp('ShapeTani',str(tani))
|
||||
w.write(m)
|
||||
|
||||
df1 = [x.strip().split('\t') for x in file(d1).readlines()]
|
||||
taniCol = df1[0].index('Shape-it::Tanimoto')
|
||||
|
||||
38
Code/Shape/Wrap/test_shape_reference2.py
Normal file
38
Code/Shape/Wrap/test_shape_reference2.py
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import rdkit
|
||||
import rdkit.Chem.rdShape
|
||||
#print rdkit.Chem.rdShape.Align.__doc__
|
||||
from rdkit import Chem
|
||||
from rdkit import RDConfig
|
||||
import unittest, os,time
|
||||
|
||||
class TestCase(unittest.TestCase) :
|
||||
def test_shape_reference(self):
|
||||
f1 = os.path.join(RDConfig.RDBaseDir,'Code','Shape','test_data','ace.sdf')
|
||||
d1 = os.path.join(RDConfig.RDBaseDir,'Code','Shape','test_data','output_ace_1.tab')
|
||||
|
||||
mol1 = Chem.SDMolSupplier(f1).next()
|
||||
mol2 = Chem.SDMolSupplier(f1).next()
|
||||
score = rdkit.Chem.rdShape.Align(mol1, mol2, maxIter=10)
|
||||
self.failUnlessAlmostEqual(score,1.0,1)
|
||||
|
||||
|
||||
#df1 = file(d1,'w+')
|
||||
df1 = [x.strip().split() for x in file(d1,'r')]
|
||||
scores = [(x,float(y)) for x,y in df1]
|
||||
supp = Chem.SDMolSupplier(f1)
|
||||
tanimoto=[]
|
||||
w = Chem.SDWriter('/tmp/shapeout.sdf')
|
||||
for i,m in enumerate(supp):
|
||||
tani = rdkit.Chem.rdShape.Align(mol1, m, maxIter=0)
|
||||
tanimoto.append(tani)
|
||||
##print >>df1,'%d %.4f'%(i,tani)
|
||||
print i,scores[i][1],'%.4f'%tani,'%.4f'%(scores[i][1]-tani)
|
||||
self.failUnlessAlmostEqual(tani,scores[i][1],1)
|
||||
m.SetProp('ShapeTani',str(tani))
|
||||
w.write(m)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -30,13 +30,13 @@ Shape-it is linked against OpenBabel version 2.
|
||||
|
||||
#include <Shape/gaussianVolume.h>
|
||||
#include <Shape/solutionInfo.h>
|
||||
#include <eigen3/Eigen/Dense>
|
||||
|
||||
|
||||
GaussianVolume::GaussianVolume(void)
|
||||
:volume(0.0)
|
||||
, overlap(0.0)
|
||||
, centroid(0.0, 0.0, 0.0)
|
||||
, rotation(3, 3, 0.0)
|
||||
, gaussians()
|
||||
, childOverlaps()
|
||||
, levels()
|
||||
@@ -366,11 +366,13 @@ void initOrientation(GaussianVolume & gv)
|
||||
gv.centroid.y /= gv.volume;
|
||||
gv.centroid.z /= gv.volume;
|
||||
|
||||
|
||||
//#define USE_EIGEN2
|
||||
// Compute moments of inertia from mass matrix
|
||||
//RDNumeric::DoubleSymmMatrix mass;
|
||||
SiMath::Matrix mass(3, 3, 0.0);
|
||||
|
||||
#ifdef USE_EIGEN2
|
||||
double sumXX=0,sumXY=0,sumXZ=0,sumYY=0,sumYZ=0,sumZZ=0;
|
||||
#else
|
||||
RDNumeric::DoubleSymmMatrix mass(3,0.0);
|
||||
#endif
|
||||
// Loop over all gaussians
|
||||
for (std::vector < AtomGaussian >::iterator i = gv.gaussians.begin();
|
||||
i != gv.gaussians.end(); ++i) {
|
||||
@@ -384,42 +386,91 @@ void initOrientation(GaussianVolume & gv)
|
||||
z = i->center.z;
|
||||
|
||||
int mult=(i->nbr % 2)?1:-1;
|
||||
// Update upper triangle
|
||||
mass[0][0] += mult*i->volume * x * x;
|
||||
mass[0][1] += mult*i->volume * x * y;
|
||||
mass[0][2] += mult*i->volume * x * z;
|
||||
mass[1][1] += mult*i->volume * y * y;
|
||||
mass[1][2] += mult*i->volume * y * z;
|
||||
mass[2][2] += mult*i->volume * z * z;
|
||||
|
||||
#ifdef USE_EIGEN2
|
||||
sumXX += mult*i->volume * x * x;
|
||||
sumXY += mult*i->volume * x * y;
|
||||
sumXZ += mult*i->volume * x * z;
|
||||
sumYY += mult*i->volume * y * y;
|
||||
sumYZ += mult*i->volume * y * z;
|
||||
sumZZ += mult*i->volume * z * z;
|
||||
#else
|
||||
mass.setVal(0,0,mass.getVal(0,0) + mult*i->volume * x * x);
|
||||
mass.setVal(0,1,mass.getVal(0,1) + mult*i->volume * x * y);
|
||||
mass.setVal(0,2,mass.getVal(0,2) + mult*i->volume * x * z);
|
||||
mass.setVal(1,1,mass.getVal(1,1) + mult*i->volume * y * y);
|
||||
mass.setVal(1,2,mass.getVal(1,2) + mult*i->volume * y * z);
|
||||
mass.setVal(2,2,mass.getVal(2,2) + mult*i->volume * z * z);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set lower triangle
|
||||
mass[1][0] = mass[0][1];
|
||||
mass[2][0] = mass[0][2];
|
||||
mass[2][1] = mass[1][2];
|
||||
|
||||
// Normalize mass matrix
|
||||
#ifdef USE_EIGEN2
|
||||
sumXX/=gv.volume;
|
||||
sumXY/=gv.volume;
|
||||
sumXZ/=gv.volume;
|
||||
sumYY/=gv.volume;
|
||||
sumYZ/=gv.volume;
|
||||
sumZZ/=gv.volume;
|
||||
Eigen::Matrix3d mat;
|
||||
mat << sumXX, sumXY, sumXZ,
|
||||
sumXY, sumYY, sumYZ,
|
||||
sumXZ, sumYZ, sumZZ;
|
||||
|
||||
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver(mat);
|
||||
if(eigensolver.info()!=Eigen::Success){
|
||||
BOOST_LOG(rdErrorLog)<<"eigenvalue calculation did not converge"<<std::endl;
|
||||
return;
|
||||
}
|
||||
// std::cerr << " eigenvalues: " << eigensolver.eigenvalues() << std::endl;
|
||||
for(unsigned int i=0;i<3;++i){
|
||||
for(unsigned int j=0;j<3;++j){
|
||||
// the eigenvectors come back in increasing order, so reverse it here:
|
||||
gv.rotation[i][j] = eigensolver.eigenvectors()(i,2-j);
|
||||
}
|
||||
}
|
||||
#else
|
||||
mass /= gv.volume;
|
||||
|
||||
// Compute SVD of the mass matrix
|
||||
SiMath::SVD svd(mass, true, true);
|
||||
gv.rotation = svd.getU();
|
||||
|
||||
int nPts = gv.gaussians.size();
|
||||
RDGeom::Transform3D *tf=RDNumeric::computeCanonicalTransformFromCovMat(&mass,nPts);
|
||||
for(unsigned int i=0;i<3;++i){
|
||||
for(unsigned int j=0;j<3;++j){
|
||||
gv.rotation[i][j] = tf->getVal(j,i);
|
||||
}
|
||||
}
|
||||
delete tf;
|
||||
#endif
|
||||
#if 0
|
||||
std::cerr<<std::endl;
|
||||
for(unsigned int i=0;i<3;++i){
|
||||
for(unsigned int j=0;j<3;++j){
|
||||
std::cerr<<std::setprecision(5)<<gv.rotation[i][j]<<" ";
|
||||
}
|
||||
std::cerr<<std::endl;
|
||||
}
|
||||
#endif
|
||||
double det = gv.rotation[0][0] * gv.rotation[1][1] * gv.rotation[2][2]
|
||||
+ gv.rotation[2][1] * gv.rotation[1][0] * gv.rotation[0][2]
|
||||
+ gv.rotation[0][1] * gv.rotation[1][2] * gv.rotation[2][0]
|
||||
- gv.rotation[0][0] * gv.rotation[1][2] * gv.rotation[2][1]
|
||||
- gv.rotation[1][1] * gv.rotation[2][0] * gv.rotation[0][2]
|
||||
- gv.rotation[2][2] * gv.rotation[0][1] * gv.rotation[1][0];
|
||||
|
||||
//std::cerr<<" DET: "<<std::setprecision(3)<<det<<std::endl;
|
||||
// Check if it is a rotation matrix and not a mirroring
|
||||
if (det < 0) {
|
||||
//std::cerr<<"FLIP"<<std::endl;
|
||||
#if 1
|
||||
// Switch sign of third column
|
||||
gv.rotation[0][2] = -gv.rotation[0][2];
|
||||
gv.rotation[1][2] = -gv.rotation[1][2];
|
||||
gv.rotation[2][2] = -gv.rotation[2][2];
|
||||
#else
|
||||
for(unsigned int i=0;i<3;++i){
|
||||
for(unsigned int j=0;j<3;++j){
|
||||
gv.rotation[i][j]*=-1.;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Rotate all gaussians
|
||||
for (std::vector < AtomGaussian >::iterator i = gv.gaussians.begin();
|
||||
i != gv.gaussians.end(); ++i) {
|
||||
|
||||
@@ -44,10 +44,14 @@ Shape-it is linked against OpenBabel version 2.
|
||||
#include <GraphMol/ROMol.h>
|
||||
#include <GraphMol/PeriodicTable.h>
|
||||
#include <GraphMol/AtomIterators.h>
|
||||
#include <Geometry/point.h>
|
||||
#include <Numerics/Matrix.h>
|
||||
#include <Numerics/SymmMatrix.h>
|
||||
#include <Numerics/Alignment/AlignPoints.h>
|
||||
|
||||
|
||||
// Shape-it
|
||||
#include <Shape/siMath.h>
|
||||
#include <Geometry/point.h>
|
||||
#include <Shape/atomGaussian.h>
|
||||
#include <Shape/alignmentInfo.h>
|
||||
|
||||
@@ -65,17 +69,18 @@ const double PENALTY = 5.00;
|
||||
|
||||
|
||||
class GaussianVolume {
|
||||
public:
|
||||
double volume; ///< Molecular volume
|
||||
double overlap; ///< Self-overlap of the molecule
|
||||
RDGeom::Point3D centroid; ///< center of the gaussian volume
|
||||
SiMath::Matrix rotation; ///< rotation matrix to align molecule to principal axes
|
||||
std::vector < AtomGaussian > gaussians; ///< vector of all atom gaussians and their overlaps
|
||||
std::vector < std::vector < unsigned int >*>childOverlaps; ///< vector to keep track of which overlaps are formed with one gaussian
|
||||
std::vector < unsigned int >levels; ///< indicates where in the vector the level of overlaps changes
|
||||
public:
|
||||
double volume; ///< Molecular volume
|
||||
double overlap; ///< Self-overlap of the molecule
|
||||
RDGeom::Point3D centroid; ///< center of the gaussian volume
|
||||
|
||||
GaussianVolume(void);
|
||||
~GaussianVolume(void);
|
||||
std::vector < AtomGaussian > gaussians; ///< vector of all atom gaussians and their overlaps
|
||||
std::vector < std::vector < unsigned int >*>childOverlaps; ///< vector to keep track of which overlaps are formed with one gaussian
|
||||
std::vector < unsigned int >levels; ///< indicates where in the vector the level of overlaps changes
|
||||
double rotation[3][3]; ///< rotation matrix to align molecule to principal axes
|
||||
|
||||
GaussianVolume(void);
|
||||
~GaussianVolume(void);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ Shape-it is linked against OpenBabel version 2.
|
||||
|
||||
void
|
||||
positionMolecule(RDKit::ROMol & m, RDGeom::Point3D & centroid,
|
||||
SiMath::Matrix & rotation)
|
||||
double rotation[3][3])
|
||||
{
|
||||
RDKit::ROMol::AtomIterator ai;
|
||||
RDKit::Conformer conf = m.getConformer(0);
|
||||
@@ -62,7 +62,7 @@ positionMolecule(RDKit::ROMol & m, RDGeom::Point3D & centroid,
|
||||
|
||||
|
||||
void
|
||||
repositionMolecule(RDKit::ROMol & m, SiMath::Matrix & rotation,
|
||||
repositionMolecule(RDKit::ROMol & m, double rotation[3][3],
|
||||
RDGeom::Point3D & centroid)
|
||||
{
|
||||
RDKit::ROMol::AtomIterator ai;
|
||||
|
||||
@@ -49,8 +49,8 @@ Shape-it is linked against OpenBabel version 2.
|
||||
#include <Geometry/point.h>
|
||||
|
||||
|
||||
void positionMolecule(RDKit::ROMol &, RDGeom::Point3D &, SiMath::Matrix &);
|
||||
void repositionMolecule(RDKit::ROMol &, SiMath::Matrix &, RDGeom::Point3D &);
|
||||
void positionMolecule(RDKit::ROMol &, RDGeom::Point3D &, double[3][3]);
|
||||
void repositionMolecule(RDKit::ROMol &, double[3][3], RDGeom::Point3D &);
|
||||
void rotateMolecule(RDKit::ROMol &, SiMath::Vector &);
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,8 @@ SolutionInfo shape(RDKit::ROMol & refMol, RDKit::ROMol & dbMol,
|
||||
bestSolution.refName = refName;
|
||||
bestSolution.refAtomVolume = refVolume.overlap;
|
||||
bestSolution.refCenter = refVolume.centroid;
|
||||
bestSolution.refRotation = refVolume.rotation;
|
||||
memcpy(static_cast<void *>(bestSolution.refRotation),static_cast<void *>(refVolume.rotation),
|
||||
3*3*sizeof(double));
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -828,442 +828,6 @@ SiMath::Vector
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SVD::SVD(const Matrix & Aorig, bool bU, bool bV):
|
||||
_m(Aorig.nbrRows()),
|
||||
_n(Aorig.nbrColumns()), _U(), _V(), _S(0), _computeV(bV), _computeU(bU)
|
||||
{
|
||||
// dimensionality of the problem
|
||||
int nu = min(_m, _n);
|
||||
int nct = min(_m - 1, _n);
|
||||
int nrt = max(0, std::min(_n - 2, _m));
|
||||
|
||||
// define the dimensions of the internal matrices and vetors
|
||||
_S.reset(min(_m + 1, _n));
|
||||
|
||||
if (_computeU)
|
||||
_U.reset(_m, nu);
|
||||
|
||||
if (_computeV)
|
||||
_V.reset(_n, _n);
|
||||
|
||||
// local working vectors
|
||||
Vector e(_n);
|
||||
Vector work(_m);
|
||||
|
||||
// make a copy of A to do the computations on
|
||||
Matrix Acopy(Aorig);
|
||||
|
||||
// loop indices
|
||||
int i = 0, j = 0, k = 0;
|
||||
|
||||
// Reduce A to bidiagonal form, storing the diagonal elements
|
||||
// in _S and the super-diagonal elements in e.
|
||||
|
||||
for (k = 0; k < max(nct, nrt); k++) {
|
||||
if (k < nct) {
|
||||
// Compute the transformation for the k-th column and place the k-th diagonal in _S[k].
|
||||
_S[k] = 0;
|
||||
for (i = k; i < _m; i++) {
|
||||
_S[k] = triangle(_S[k], Acopy[i][k]);
|
||||
}
|
||||
if (_S[k] != 0.0) {
|
||||
if (Acopy[k][k] < 0.0) {
|
||||
_S[k] = -_S[k];
|
||||
}
|
||||
for (i = k; i < _m; i++) {
|
||||
Acopy[i][k] /= _S[k];
|
||||
}
|
||||
Acopy[k][k] += 1.0;
|
||||
}
|
||||
_S[k] = -_S[k];
|
||||
}
|
||||
for (j = k + 1; j < _n; j++) {
|
||||
if ((k < nct) && (_S[k] != 0.0)) {
|
||||
// Apply the transformation to Acopy
|
||||
double t = 0;
|
||||
for (i = k; i < _m; i++) {
|
||||
t += Acopy[i][k] * Acopy[i][j];
|
||||
}
|
||||
t = -t / Acopy[k][k];
|
||||
for (i = k; i < _m; i++) {
|
||||
Acopy[i][j] += t * Acopy[i][k];
|
||||
}
|
||||
}
|
||||
// Place the k-th row of A into e for the subsequent calculation of the row transformation.
|
||||
e[j] = Acopy[k][j];
|
||||
}
|
||||
|
||||
// Place the transformation in _U for subsequent back multiplication.
|
||||
if (_computeU & (k < nct)) {
|
||||
for (i = k; i < _m; i++) {
|
||||
_U[i][k] = Acopy[i][k];
|
||||
}
|
||||
}
|
||||
|
||||
if (k < nrt) {
|
||||
// Compute the k-th row transformation and place the k-th super-diagonal in e[k].
|
||||
// Compute 2-norm without under/overflow.
|
||||
e[k] = 0.0;
|
||||
for (i = k + 1; i < _n; i++) {
|
||||
e[k] = triangle(e[k], e[i]);
|
||||
}
|
||||
if (e[k] != 0.0) {
|
||||
if (e[k + 1] < 0.0) { // switch sign
|
||||
e[k] = -e[k];
|
||||
}
|
||||
for (i = k + 1; i < _n; i++) { // scale
|
||||
e[i] /= e[k];
|
||||
}
|
||||
e[k + 1] += 1.0;
|
||||
}
|
||||
e[k] = -e[k];
|
||||
if ((k + 1 < _m) & (e[k] != 0.0)) {
|
||||
// Apply the transformation.
|
||||
|
||||
for (i = k + 1; i < _m; i++) {
|
||||
work[i] = 0.0;
|
||||
}
|
||||
for (j = k + 1; j < _n; j++) {
|
||||
for (i = k + 1; i < _m; i++) {
|
||||
work[i] += e[j] * Acopy[i][j];
|
||||
}
|
||||
}
|
||||
for (j = k + 1; j < _n; j++) {
|
||||
double t = -e[j] / e[k + 1];
|
||||
for (i = k + 1; i < _m; i++) {
|
||||
Acopy[i][j] += t * work[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Place the transformation in _V for subsequent back multiplication.
|
||||
if (_computeV) {
|
||||
for (i = k + 1; i < _n; i++) {
|
||||
_V[i][k] = e[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the final bidiagonal matrix of order p.
|
||||
int p = min(_n, _m + 1);
|
||||
if (nct < _n) {
|
||||
_S[nct] = Acopy[nct][nct];
|
||||
}
|
||||
if (_m < p) {
|
||||
_S[p - 1] = 0.0;
|
||||
}
|
||||
if (nrt + 1 < p) {
|
||||
e[nrt] = Acopy[nrt][p - 1];
|
||||
}
|
||||
e[p - 1] = 0.0;
|
||||
|
||||
// If required, generate U.
|
||||
if (_computeU) {
|
||||
for (j = nct; j < nu; j++) {
|
||||
for (i = 0; i < _m; i++) {
|
||||
_U[i][j] = 0.0;
|
||||
}
|
||||
_U[j][j] = 1.0;
|
||||
}
|
||||
for (k = nct - 1; k >= 0; k--) {
|
||||
if (_S[k] != 0.0) {
|
||||
for (j = k + 1; j < nu; j++) {
|
||||
double t = 0;
|
||||
for (i = k; i < _m; i++) {
|
||||
t += _U[i][k] * _U[i][j];
|
||||
}
|
||||
t = -t / _U[k][k];
|
||||
for (i = k; i < _m; i++) {
|
||||
_U[i][j] += t * _U[i][k];
|
||||
}
|
||||
}
|
||||
for (i = k; i < _m; i++) {
|
||||
_U[i][k] = -_U[i][k];
|
||||
}
|
||||
_U[k][k] = 1.0 + _U[k][k];
|
||||
for (i = 0; i < k - 1; i++) {
|
||||
_U[i][k] = 0.0;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < _m; i++) {
|
||||
_U[i][k] = 0.0;
|
||||
}
|
||||
_U[k][k] = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If required, generate _V.
|
||||
if (_computeV) {
|
||||
for (k = _n - 1; k >= 0; k--) {
|
||||
if ((k < nrt) & (e[k] != 0.0)) {
|
||||
for (j = k + 1; j < nu; j++) {
|
||||
double t = 0;
|
||||
for (i = k + 1; i < _n; i++) {
|
||||
t += _V[i][k] * _V[i][j];
|
||||
}
|
||||
t = -t / _V[k + 1][k];
|
||||
for (i = k + 1; i < _n; i++) {
|
||||
_V[i][j] += t * _V[i][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < _n; i++) {
|
||||
_V[i][k] = 0.0;
|
||||
}
|
||||
_V[k][k] = 1.0;
|
||||
}
|
||||
}
|
||||
// Main iteration loop for the singular values.
|
||||
int pp = p - 1;
|
||||
int iter = 0;
|
||||
double eps = pow(2.0, -52.0);
|
||||
while (p > 0) {
|
||||
k = 0;
|
||||
unsigned int mode = 0;
|
||||
|
||||
// Here is where a test for too many iterations would go.
|
||||
// This section of the program inspects for negligible elements in the s and e arrays.
|
||||
// On completion the variables mode and k are set as follows.
|
||||
|
||||
// mode = 1 if s(p) and e[k-1] are negligible and k<p
|
||||
// mode = 2 if s(k) is negligible and k<p
|
||||
// mode = 3 if e[k-1] is negligible, k<p, and s(k), ..., s(p) are not negligible (qr step).
|
||||
// mode = 4 if e(p-1) is negligible (convergence).
|
||||
for (k = p - 2; k >= -1; k--) {
|
||||
if (k == -1) {
|
||||
break;
|
||||
}
|
||||
if (fabs(e[k]) <= eps * (fabs(_S[k]) + fabs(_S[k + 1]))) {
|
||||
e[k] = 0.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k == p - 2) {
|
||||
mode = 4;
|
||||
} else {
|
||||
int ks(p - 1); // start from ks == p-1
|
||||
for (; ks >= k; ks--) {
|
||||
if (ks == k) {
|
||||
break;
|
||||
}
|
||||
double t =
|
||||
((ks != p) ? fabs(e[ks]) : 0.0) + ((ks !=
|
||||
k +
|
||||
1) ? fabs(e[ks -
|
||||
1]) :
|
||||
0.0);
|
||||
if (fabs(_S[ks]) <= eps * t) {
|
||||
_S[ks] = 0.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ks == k) {
|
||||
mode = 3;
|
||||
} else if (ks == p - 1) {
|
||||
mode = 1;
|
||||
} else {
|
||||
mode = 2;
|
||||
k = ks;
|
||||
}
|
||||
}
|
||||
k++;
|
||||
|
||||
// Perform the task indicated by the selected mode.
|
||||
switch (mode) {
|
||||
|
||||
case 1:
|
||||
{ // Deflate negligible _S[p]
|
||||
double f = e[p - 2];
|
||||
e[p - 2] = 0.0;
|
||||
for (j = p - 2; j >= k; j--) {
|
||||
double t = SiMath::triangle(_S[j], f);
|
||||
double cs = _S[j] / t;
|
||||
double sn = f / t;
|
||||
_S[j] = t;
|
||||
if (j != k) {
|
||||
f = -sn * e[j - 1];
|
||||
e[j - 1] = cs * e[j - 1];
|
||||
}
|
||||
// update V
|
||||
if (_computeV) {
|
||||
for (i = 0; i < _n; i++) {
|
||||
t = cs * _V[i][j] + sn * _V[i][p - 1];
|
||||
_V[i][p - 1] =
|
||||
-sn * _V[i][j] + cs * _V[i][p - 1];
|
||||
_V[i][j] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break; // end case 1
|
||||
|
||||
case 2:
|
||||
{ // Split at negligible _S[k]
|
||||
double f = e[k - 1];
|
||||
e[k - 1] = 0.0;
|
||||
for (j = k; j < p; j++) {
|
||||
double t = triangle(_S[j], f);
|
||||
double cs = _S[j] / t;
|
||||
double sn = f / t;
|
||||
_S[j] = t;
|
||||
f = -sn * e[j];
|
||||
e[j] = cs * e[j];
|
||||
|
||||
if (_computeU) {
|
||||
for (i = 0; i < _m; i++) {
|
||||
t = cs * _U[i][j] + sn * _U[i][k - 1];
|
||||
_U[i][k - 1] =
|
||||
-sn * _U[i][j] + cs * _U[i][k - 1];
|
||||
_U[i][j] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break; // end case 2
|
||||
|
||||
case 3:
|
||||
{ // Perform one qr step.
|
||||
|
||||
// Calculate the shift.
|
||||
double scale =
|
||||
max(max
|
||||
(max
|
||||
(max(fabs(_S[p - 1]), fabs(_S[p - 2])),
|
||||
fabs(e[p - 2])), fabs(_S[k])), fabs(e[k]));
|
||||
double sp = _S[p - 1] / scale;
|
||||
double spm1 = _S[p - 2] / scale;
|
||||
double epm1 = e[p - 2] / scale;
|
||||
double sk = _S[k] / scale;
|
||||
double ek = e[k] / scale;
|
||||
double b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2.0;
|
||||
double c = (sp * epm1) * (sp * epm1);
|
||||
double shift = 0.0;
|
||||
if ((b != 0.0) || (c != 0.0)) {
|
||||
shift = sqrt(b * b + c);
|
||||
if (b < 0.0) {
|
||||
shift = -shift;
|
||||
}
|
||||
shift = c / (b + shift);
|
||||
}
|
||||
double f = (sk + sp) * (sk - sp) + shift;
|
||||
double g = sk * ek;
|
||||
|
||||
// Chase zeros.
|
||||
|
||||
for (j = k; j < p - 1; j++) {
|
||||
double t = SiMath::triangle(f, g);
|
||||
double cs = f / t;
|
||||
double sn = g / t;
|
||||
if (j != k) {
|
||||
e[j - 1] = t;
|
||||
}
|
||||
f = cs * _S[j] + sn * e[j];
|
||||
e[j] = cs * e[j] - sn * _S[j];
|
||||
g = sn * _S[j + 1];
|
||||
_S[j + 1] = cs * _S[j + 1];
|
||||
|
||||
if (_computeV) {
|
||||
for (i = 0; i < _n; i++) {
|
||||
t = cs * _V[i][j] + sn * _V[i][j + 1];
|
||||
_V[i][j + 1] =
|
||||
-sn * _V[i][j] + cs * _V[i][j + 1];
|
||||
_V[i][j] = t;
|
||||
}
|
||||
}
|
||||
t = SiMath::triangle(f, g);
|
||||
cs = f / t;
|
||||
sn = g / t;
|
||||
_S[j] = t;
|
||||
f = cs * e[j] + sn * _S[j + 1];
|
||||
_S[j + 1] = -sn * e[j] + cs * _S[j + 1];
|
||||
g = sn * e[j + 1];
|
||||
e[j + 1] = cs * e[j + 1];
|
||||
|
||||
if (_computeU && (j < _m - 1)) {
|
||||
for (i = 0; i < _m; i++) {
|
||||
t = cs * _U[i][j] + sn * _U[i][j + 1];
|
||||
_U[i][j + 1] =
|
||||
-sn * _U[i][j] + cs * _U[i][j + 1];
|
||||
_U[i][j] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
e[p - 2] = f;
|
||||
iter++;
|
||||
}
|
||||
break; // end case 3
|
||||
|
||||
// convergence step
|
||||
case 4:
|
||||
{
|
||||
|
||||
// Make the singular values positive.
|
||||
if (_S[k] <= 0.0) {
|
||||
_S[k] = (_S[k] < 0.0) ? -_S[k] : 0.0;
|
||||
|
||||
if (_computeV) {
|
||||
for (i = 0; i <= pp; i++) {
|
||||
_V[i][k] = -_V[i][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Order the singular values.
|
||||
while (k < pp) {
|
||||
if (_S[k] >= _S[k + 1])
|
||||
break;
|
||||
|
||||
// swap values and columns if necessary
|
||||
_S.swap(k, k + 1);
|
||||
|
||||
if (_computeV && (k < _n - 1))
|
||||
_V.swapColumns(k, k + 1);
|
||||
|
||||
if (_computeU && (k < _m - 1))
|
||||
_U.swapColumns(k, k + 1);
|
||||
|
||||
k++;
|
||||
}
|
||||
iter = 0;
|
||||
p--;
|
||||
}
|
||||
break; // end case 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Matrix SVD::getSingularMatrix()
|
||||
{
|
||||
unsigned int n = _S.size();
|
||||
Matrix A(n, n, 0.0);
|
||||
// set diagonal elements
|
||||
for (int i = 0; i < n; i++) {
|
||||
A[i][i] = _S[i];
|
||||
}
|
||||
|
||||
return A;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int SVD::rank()
|
||||
{
|
||||
double eps = pow(2.0, -52.0);
|
||||
double tol = max(_m, _n) * _S[0] * eps;
|
||||
int r = 0;
|
||||
for (int i = 0; i < _S.size(); i++) {
|
||||
if (_S[i] > tol) {
|
||||
r++;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double SiMath::randD(double a, double b)
|
||||
{
|
||||
double d(a);
|
||||
|
||||
@@ -246,53 +246,8 @@ namespace SiMath {
|
||||
Vector colProduct(const Vector & U, const Matrix & A);
|
||||
|
||||
|
||||
|
||||
class SVD {
|
||||
public:
|
||||
|
||||
SVD(const Matrix &, bool bU = true, bool bV = true);
|
||||
|
||||
Vector getSingularValues() {
|
||||
return _S;
|
||||
};
|
||||
Matrix getSingularMatrix();
|
||||
|
||||
Matrix getU() {
|
||||
return _U;
|
||||
};
|
||||
Matrix getV() {
|
||||
return _V;
|
||||
};
|
||||
|
||||
double norm2() {
|
||||
return _S[0];
|
||||
};
|
||||
|
||||
double cond() {
|
||||
return _S[0] / _S[_S.size() - 1];
|
||||
};
|
||||
|
||||
int rank();
|
||||
|
||||
private:
|
||||
|
||||
int _m; ///< number of rows
|
||||
int _n; ///< number of columns
|
||||
Matrix _U; ///< Left singular vectors
|
||||
Matrix _V; ///< Right singular vectors
|
||||
Vector _S; ///< Singular values
|
||||
|
||||
bool _computeV; ///< Check if V should be computed
|
||||
bool _computeU; ///< Check if U should be computed
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
double randD(double, double);
|
||||
|
||||
|
||||
|
||||
}; // end of namespace SiMath
|
||||
|
||||
|
||||
|
||||
@@ -36,12 +36,10 @@ SolutionInfo::SolutionInfo(void)
|
||||
:refName("")
|
||||
, refAtomVolume(0.0)
|
||||
, refCenter(0, 0, 0)
|
||||
, refRotation(3, 3, 0)
|
||||
, dbName("")
|
||||
, dbAtomVolume(0.0)
|
||||
, dbMol()
|
||||
, dbCenter(0, 0, 0)
|
||||
, dbRotation(3, 3, 0)
|
||||
, atomOverlap(0.0)
|
||||
, score(0.0)
|
||||
, rotor(4, 0.0)
|
||||
@@ -62,7 +60,7 @@ updateSolutionInfo(SolutionInfo & s, AlignmentInfo & res, double score,
|
||||
{
|
||||
s.dbAtomVolume = gv.overlap;
|
||||
s.dbCenter = gv.centroid;
|
||||
s.dbRotation = gv.rotation;
|
||||
memcpy(static_cast<void *>(s.dbRotation),static_cast<void *>(gv.rotation), 3*3*sizeof(double));
|
||||
s.atomOverlap = res.overlap;
|
||||
s.score = score;
|
||||
s.rotor = res.rotor;
|
||||
|
||||
@@ -53,25 +53,25 @@ const std::string tversky_ref = "Tversky_Ref";
|
||||
const std::string tversky_db = "Tversky_Db";
|
||||
|
||||
class SolutionInfo {
|
||||
public:
|
||||
public:
|
||||
|
||||
std::string refName;
|
||||
double refAtomVolume;
|
||||
std::string refName;
|
||||
double refAtomVolume;
|
||||
RDGeom::Point3D refCenter;
|
||||
SiMath::Matrix refRotation;
|
||||
|
||||
RDKit::ROMol * dbMol;
|
||||
std::string dbName;
|
||||
double dbAtomVolume;
|
||||
RDKit::ROMol * dbMol;
|
||||
std::string dbName;
|
||||
double dbAtomVolume;
|
||||
RDGeom::Point3D dbCenter;
|
||||
SiMath::Matrix dbRotation;
|
||||
double refRotation[3][3];
|
||||
double dbRotation[3][3];
|
||||
|
||||
double atomOverlap;
|
||||
double score;
|
||||
SiMath::Vector rotor;
|
||||
double atomOverlap;
|
||||
double score;
|
||||
SiMath::Vector rotor;
|
||||
|
||||
SolutionInfo(void);
|
||||
~SolutionInfo(void);
|
||||
SolutionInfo(void);
|
||||
~SolutionInfo(void);
|
||||
|
||||
};
|
||||
|
||||
|
||||
3989
Code/Shape/test_data/ace.orig_aligned.sdf
Normal file
3989
Code/Shape/test_data/ace.orig_aligned.sdf
Normal file
File diff suppressed because it is too large
Load Diff
5451
Code/Shape/test_data/ace.sdf
Normal file
5451
Code/Shape/test_data/ace.sdf
Normal file
File diff suppressed because it is too large
Load Diff
46
Code/Shape/test_data/output_ace_1.tab
Normal file
46
Code/Shape/test_data/output_ace_1.tab
Normal file
@@ -0,0 +1,46 @@
|
||||
0 1.0000
|
||||
1 0.7724
|
||||
2 0.7823
|
||||
3 0.6939
|
||||
4 0.6414
|
||||
5 0.6657
|
||||
6 0.5810
|
||||
7 0.5518
|
||||
8 0.5790
|
||||
9 0.5500
|
||||
10 0.4723
|
||||
11 0.5749
|
||||
12 0.6745
|
||||
13 0.7032
|
||||
14 0.6617
|
||||
15 0.6601
|
||||
16 0.6339
|
||||
17 0.5988
|
||||
18 0.6597
|
||||
19 0.5361
|
||||
20 0.5145
|
||||
21 0.4654
|
||||
22 0.6456
|
||||
23 0.4735
|
||||
24 0.5119
|
||||
25 0.4712
|
||||
26 0.4227
|
||||
27 0.5272
|
||||
28 0.5067
|
||||
29 0.3925
|
||||
30 0.4363
|
||||
31 0.4454
|
||||
32 0.4131
|
||||
33 0.3891
|
||||
34 0.4360
|
||||
35 0.3856
|
||||
36 0.4280
|
||||
37 0.3263
|
||||
38 0.3870
|
||||
39 0.4262
|
||||
40 0.4046
|
||||
41 0.3994
|
||||
42 0.3698
|
||||
43 0.3462
|
||||
44 0.3722
|
||||
45 0.3737
|
||||
Reference in New Issue
Block a user