big step in moving away from siMath; add more tests

This commit is contained in:
Greg Landrum
2013-11-17 07:34:37 +01:00
parent 6423a5965f
commit fd1e8666f2
15 changed files with 9662 additions and 543 deletions

View File

@@ -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

View File

@@ -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')

View 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()

View File

@@ -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) {

View File

@@ -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);
};

View File

@@ -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;

View File

@@ -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 &);

View File

@@ -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));

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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);
};

File diff suppressed because it is too large Load Diff

5451
Code/Shape/test_data/ace.sdf Normal file

File diff suppressed because it is too large Load Diff

View 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