mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-04 21:54:27 +08:00
1264 lines
39 KiB
C++
1264 lines
39 KiB
C++
//
|
|
// Copyright (c) 2016, Guillaume GODIN
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are
|
|
// met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above
|
|
// copyright notice, this list of conditions and the following
|
|
// disclaimer in the documentation and/or other materials provided
|
|
// with the distribution.
|
|
// * Neither the name of Institue of Cancer Research.
|
|
// nor the names of its contributors may be used to endorse or promote
|
|
// products derived from this software without specific prior written
|
|
// permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Adding GETAWAY descriptors by Guillaume Godin
|
|
// for build & set RDBASE! => export RDBASE=/Users/mbp/Github/rdkit_mine/
|
|
|
|
#include <GraphMol/RDKitBase.h>
|
|
#include <GraphMol/MolTransforms/MolTransforms.h>
|
|
|
|
#include "GETAWAY.h"
|
|
#include "PBF.h"
|
|
#include "MolData3Ddescriptors.h"
|
|
|
|
#include "GraphMol/PartialCharges/GasteigerCharges.h"
|
|
#include "GraphMol/PartialCharges/GasteigerParams.h"
|
|
#include <Numerics/EigenSolvers/PowerEigenSolver.h>
|
|
|
|
#include <Numerics/Matrix.h>
|
|
#include <Numerics/SquareMatrix.h>
|
|
#include <Numerics/SymmMatrix.h>
|
|
#include <cmath>
|
|
#include <Eigen/Dense>
|
|
#include <Eigen/SVD>
|
|
#include <deque>
|
|
#include <Eigen/Core>
|
|
#include <Eigen/QR>
|
|
|
|
using namespace Eigen;
|
|
|
|
namespace RDKit {
|
|
|
|
namespace Descriptors {
|
|
|
|
namespace {
|
|
|
|
MolData3Ddescriptors moldata3D;
|
|
|
|
double roundn(double in, int factor) {
|
|
return std::round(in * pow(10., factor)) / pow(10., factor);
|
|
}
|
|
|
|
double *retreiveMat(MatrixXd matrix) {
|
|
double *arrayd = matrix.data();
|
|
return arrayd;
|
|
}
|
|
|
|
double *retreiveVect(VectorXd matrix) {
|
|
double *arrayd = matrix.data();
|
|
return arrayd;
|
|
}
|
|
|
|
VectorXd getEigenVect(std::vector<double> v) {
|
|
double *varray_ptr = &v[0];
|
|
Map<VectorXd> V(varray_ptr, v.size());
|
|
return V;
|
|
}
|
|
|
|
double round_to_n_digits_(double x, int n) {
|
|
char buff[32];
|
|
sprintf(buff, "%.*g", n, x); // use g to have significant digits!
|
|
return atof(buff);
|
|
}
|
|
|
|
double round_to_n_digits(double x, int n) {
|
|
double scale = pow(10.0, ceil(log10(fabs(x))) + n);
|
|
return std::round(x * scale) / scale;
|
|
}
|
|
|
|
bool IsClose(double a, double b, int n) {
|
|
return (fabs(a - b) <= pow(0.1, n) * 1.1);
|
|
}
|
|
|
|
int countZeros(std::string ta) {
|
|
int nbzero = 0;
|
|
for (char i : ta) {
|
|
if (i != '0') {
|
|
break;
|
|
}
|
|
nbzero = nbzero + 1;
|
|
}
|
|
|
|
return nbzero;
|
|
}
|
|
|
|
bool IsClose2(double a, double b, unsigned int) {
|
|
bool isclose = false;
|
|
|
|
std::string sa, sb;
|
|
std::string ta, tb;
|
|
std::stringstream outa, outb;
|
|
outa << a;
|
|
sa = outa.str();
|
|
outb << b;
|
|
sb = outb.str();
|
|
ta = sa.substr(sa.find('.') + 1);
|
|
tb = sb.substr(sb.find('.') + 1);
|
|
|
|
// same number of digits!
|
|
if (countZeros(ta) == countZeros(tb)) {
|
|
if (ta.length() > tb.length()) {
|
|
tb += '0';
|
|
}
|
|
if (ta.length() < tb.length()) {
|
|
ta += '0';
|
|
}
|
|
}
|
|
// std::cout << tb << ":"<< atoi(tb.c_str()) << ":" << countZeros(ta) <<
|
|
// "\n";
|
|
// std::cout << ta << ":"<< atoi(ta.c_str()) << ":" << countZeros(ta) <<
|
|
// "\n";
|
|
|
|
if (ta.length() == tb.length()) {
|
|
// last digit +/-1 deviation only!)
|
|
if (abs(atoi(ta.c_str()) - atoi(tb.c_str())) < 2) {
|
|
// std::cout << a << "," << b << " ta:" << ta << "," << "tb:" << tb<<
|
|
// "\n";
|
|
isclose = true;
|
|
}
|
|
}
|
|
return isclose;
|
|
}
|
|
|
|
bool IsClose3(double a, double b, unsigned int) {
|
|
bool isclose = false;
|
|
std::string sa, sb;
|
|
std::string ta, tb;
|
|
std::stringstream outa, outb;
|
|
outa << a;
|
|
sa = outa.str();
|
|
outb << b;
|
|
sb = outb.str();
|
|
ta = sa.substr(sa.find('.') + 1);
|
|
tb = sb.substr(sb.find('.') + 1);
|
|
// same number of digits!
|
|
if (ta.length() == tb.length()) {
|
|
// last digit +/-1 deviation only!)
|
|
if (abs(atoi(ta.c_str()) - atoi(tb.c_str())) < 2) {
|
|
// std::cout << a << "," << b << " ta:" << ta << "," << "tb:" << tb<<
|
|
// "\n";
|
|
isclose = true;
|
|
}
|
|
}
|
|
return isclose;
|
|
}
|
|
|
|
// need to clean that code to have always the same output which is not the case
|
|
// the classes used the last 2 digit +/- 1 to cluster in the same group (with 3
|
|
// digit precision)
|
|
// 0.012 and 0.013 are in the same group while 0.014 are not!
|
|
std::vector<double> clusterArray(std::vector<double> data, double precision) {
|
|
std::vector<double> Store;
|
|
|
|
// sort the input data
|
|
std::sort(data.begin(), data.end());
|
|
|
|
// find the difference between each number and its predecessor
|
|
std::vector<double> diffs;
|
|
|
|
std::adjacent_difference(data.begin(), data.end(), std::back_inserter(diffs));
|
|
|
|
// convert differences into percentage changes
|
|
// std::transform(diffs.begin(), diffs.end(), data.begin(), diffs.begin(),
|
|
// std::divides<double>());
|
|
|
|
int count = 0;
|
|
for (unsigned int i = 0; i < data.size(); i++) {
|
|
// std::cout << diffs[i] << ",";
|
|
count++;
|
|
// if a difference exceeds 0.01 <=> 1%, start a new group: if transform is
|
|
// used!
|
|
// use diff not ratio (with 0.003 precision look like it's what it's used in
|
|
// Dragon 6!)
|
|
if (diffs[i] > pow(0.1, precision)) {
|
|
Store.push_back(count);
|
|
count = 0;
|
|
}
|
|
}
|
|
|
|
return Store;
|
|
}
|
|
|
|
// need to clean that code to have always the same output which is not the case
|
|
// the classes used the last 2 digit +/- 1 to cluster in the same group (with 3
|
|
// digit precision)
|
|
// 0.012 and 0.013 are in the same group while 0.014 are not!
|
|
// alternative clustering method not working as in Dragon
|
|
std::vector<double> clusterArray2(std::vector<double> data,
|
|
unsigned int precision) {
|
|
std::vector<double> Store;
|
|
|
|
// sort the input data descend order!
|
|
std::sort(data.begin(), data.end(), std::greater<double>());
|
|
std::deque<double> B(data.begin(), data.end());
|
|
|
|
int count = 0;
|
|
while (!B.empty()) {
|
|
double dk = B.front();
|
|
B.pop_front();
|
|
count++;
|
|
// case where the last value is not grouped it goes to the single last group
|
|
if (B.empty()) {
|
|
Store.push_back(count);
|
|
}
|
|
|
|
for (unsigned int i = 0; i < B.size(); i++) {
|
|
if (IsClose2(dk, B[i], precision)) {
|
|
count++;
|
|
} else {
|
|
Store.push_back(count);
|
|
for (unsigned int j = 0; j < i; j++) {
|
|
B.pop_front();
|
|
}
|
|
count = 0;
|
|
break;
|
|
}
|
|
|
|
if (i == B.size() - 1) {
|
|
Store.push_back(count);
|
|
B.pop_front();
|
|
count = 0;
|
|
}
|
|
}
|
|
}
|
|
return Store;
|
|
}
|
|
|
|
std::vector<double> GetGeodesicMatrix(const double *dist, int lag,
|
|
int numAtoms) {
|
|
PRECONDITION(dist != nullptr, "bad array");
|
|
|
|
int sizeArray = numAtoms * numAtoms;
|
|
std::vector<double> Geodesic;
|
|
Geodesic.resize(sizeArray);
|
|
std::transform(dist, dist + sizeArray, Geodesic.begin(),
|
|
[lag](double dist) { return int(dist == lag); });
|
|
|
|
return Geodesic;
|
|
}
|
|
|
|
JacobiSVD<MatrixXd> getSVD(const MatrixXd &A) {
|
|
JacobiSVD<MatrixXd> mysvd(A, ComputeThinU | ComputeThinV);
|
|
return mysvd;
|
|
}
|
|
|
|
MatrixXd GetPinv(const MatrixXd &A) {
|
|
JacobiSVD<MatrixXd> svd = getSVD(A);
|
|
double pinvtoler = 1.e-3; // choose your tolerance wisely!
|
|
VectorXd vs = svd.singularValues();
|
|
VectorXd vsinv = svd.singularValues();
|
|
|
|
for (unsigned int i = 0; i < A.cols(); ++i) {
|
|
if (vs(i) > pinvtoler) {
|
|
vsinv(i) = 1.0 / vs(i);
|
|
} else {
|
|
vsinv(i) = 0.0;
|
|
}
|
|
}
|
|
|
|
MatrixXd S = vsinv.asDiagonal();
|
|
MatrixXd Ap = svd.matrixV() * S * svd.matrixU().transpose();
|
|
return Ap;
|
|
}
|
|
|
|
MatrixXd GetCenterMatrix(MatrixXd Mat) {
|
|
VectorXd v = Mat.colwise().mean();
|
|
MatrixXd X = Mat.rowwise() - v.transpose();
|
|
return X;
|
|
}
|
|
|
|
MatrixXd GetHmatrix(MatrixXd X) {
|
|
MatrixXd Weighted = X.transpose() * X;
|
|
return X * GetPinv(Weighted) * X.transpose();
|
|
}
|
|
|
|
MatrixXd GetRmatrix(MatrixXd H, MatrixXd DM, int numAtoms) {
|
|
MatrixXd R = MatrixXd::Zero(numAtoms, numAtoms);
|
|
for (int i = 0; i < numAtoms - 1; i++) {
|
|
for (int j = i + 1; j < numAtoms; j++) {
|
|
R(i, j) = sqrt(H(i, i) * H(j, j)) / DM(i, j);
|
|
R(j, i) = R(i, j);
|
|
}
|
|
}
|
|
|
|
return R;
|
|
}
|
|
|
|
std::vector<int> GetHeavyList(const ROMol &mol) {
|
|
int numAtoms = mol.getNumAtoms();
|
|
std::vector<int> HeavyList;
|
|
HeavyList.reserve(numAtoms);
|
|
for (int i = 0; i < numAtoms; ++i) {
|
|
const RDKit::Atom *atom = mol.getAtomWithIdx(i);
|
|
HeavyList.push_back(int(atom->getAtomicNum() > 1));
|
|
}
|
|
return HeavyList;
|
|
}
|
|
|
|
double *AppendDouble(double *w, const double *Append, int length, int pos) {
|
|
PRECONDITION(w != nullptr, "bad array");
|
|
PRECONDITION(Append != nullptr, "bad array");
|
|
|
|
for (int i = pos; i < pos + length; i++) {
|
|
w[i] = Append[i - pos];
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
double getRCON(MatrixXd R, MatrixXd Adj, int numAtoms) {
|
|
// similar implementation of J. Chem. Inf. Comput. Sci. 2004, 44, 200-209
|
|
// equation 1 or 2 page 201
|
|
// we use instead of atomic absolute values the atomic relative ones as in
|
|
// Dragon
|
|
double RCON = 0.0;
|
|
VectorXd VSR = R.rowwise().sum();
|
|
for (int i = 0; i < numAtoms - 1; ++i) {
|
|
for (int j = i + 1; j < numAtoms; ++j) {
|
|
if (Adj(i, j) > 0) {
|
|
RCON +=
|
|
sqrt(VSR(i) * VSR(j)); // the sqrt is in the sum not over the sum!
|
|
}
|
|
}
|
|
}
|
|
return RCON;
|
|
}
|
|
|
|
double getHATS(double W1, double W2, double H1, double H2) {
|
|
return W1 * H1 * W2 * H2;
|
|
}
|
|
|
|
double getH(double W1, double W2, double H) { return W1 * H * W2; }
|
|
|
|
double getMax(const double *Rk) {
|
|
PRECONDITION(Rk != nullptr, "bad rK");
|
|
double RTp = 0;
|
|
for (int j = 0; j < 8; j++) {
|
|
if (Rk[j] > RTp) {
|
|
RTp = Rk[j];
|
|
}
|
|
}
|
|
return RTp;
|
|
}
|
|
|
|
void getGETAWAYDescCustom(MatrixXd H, MatrixXd R, MatrixXd Adj, int numAtoms,
|
|
const std::vector<int> &Heavylist, const ROMol &mol,
|
|
std::vector<double> &res, unsigned int precision,
|
|
const std::string &customAtomPropName) {
|
|
// prepare data for Getaway parameter computation
|
|
// compute parameters
|
|
|
|
VectorXd Lev = H.diagonal();
|
|
std::vector<double> heavyLev;
|
|
|
|
for (int i = 0; i < numAtoms; i++) {
|
|
if (Heavylist[i] == 1) {
|
|
heavyLev.push_back(round_to_n_digits_(Lev(i), precision));
|
|
}
|
|
}
|
|
|
|
std::vector<double> Clus = clusterArray2(heavyLev, precision);
|
|
|
|
double numHeavy = heavyLev.size();
|
|
double ITH0 = numHeavy * log(numHeavy) / log(2.0);
|
|
double ITH = ITH0;
|
|
for (double Clu : Clus) {
|
|
ITH -= Clu * log(Clu) / log(2.0);
|
|
}
|
|
res[0] = roundn(ITH, 3); // issue sometime with this due to cluster
|
|
double ISH = ITH / ITH0;
|
|
res[1] = roundn(ISH, 3); // issue sometime with this due to cluster
|
|
|
|
// use the PBF to determine 2D vs 3D (with Threshold)
|
|
// determine if this is a plane molecule
|
|
double pbf = RDKit::Descriptors::PBF(mol);
|
|
double D;
|
|
if (pbf < 1.e-5) {
|
|
D = 2.0;
|
|
} else {
|
|
D = 3.0;
|
|
}
|
|
|
|
// what about linear molecule ie (D=1) ?
|
|
double HIC = 0.0;
|
|
for (int i = 0; i < numAtoms; i++) {
|
|
HIC -= H(i, i) / D * log(H(i, i) / D) / log(2);
|
|
}
|
|
res[2] = roundn(HIC, 3);
|
|
|
|
double HGM = 1.0;
|
|
for (int i = 0; i < numAtoms; i++) {
|
|
HGM = HGM * H(i, i);
|
|
}
|
|
HGM = 100.0 * pow(HGM, 1.0 / numAtoms);
|
|
res[3] = roundn(HGM, 3);
|
|
|
|
double RARS = R.rowwise().sum().sum() / numAtoms;
|
|
|
|
JacobiSVD<MatrixXd> mysvd = getSVD(R);
|
|
|
|
VectorXd EIG = mysvd.singularValues();
|
|
|
|
double rcon = getRCON(R, std::move(Adj), numAtoms);
|
|
|
|
std::vector<double> customAtomArray =
|
|
moldata3D.GetCustomAtomProp(mol, customAtomPropName);
|
|
VectorXd Wc = getEigenVect(customAtomArray);
|
|
|
|
MatrixXd Bi;
|
|
MatrixXd RBw;
|
|
double HATSc, HATSct, H0ct, R0ct, H0c, R0c, Rkmaxc, tmpc;
|
|
double HATSk[9];
|
|
double Hk[9];
|
|
double Rk[8];
|
|
double Rp[8];
|
|
|
|
double *dist =
|
|
MolOps::getDistanceMat(mol, false); // need to be be set to false to have
|
|
// topological distance not weighted!
|
|
|
|
Map<MatrixXd> D2(dist, numAtoms, numAtoms);
|
|
|
|
double Dmax = D2.colwise().maxCoeff().maxCoeff();
|
|
|
|
HATSct = 0.0;
|
|
H0ct = 0.0;
|
|
R0ct = 0.0;
|
|
|
|
// need to loop other all the D values so <= not <!
|
|
for (int i = 0; i <= Dmax; i++) {
|
|
if (i == 0) {
|
|
Bi = H.diagonal().asDiagonal();
|
|
}
|
|
|
|
HATSc = 0.0;
|
|
H0c = 0.0;
|
|
|
|
if (i == 0) { // use Bi
|
|
for (int j = 0; j < numAtoms; j++) {
|
|
for (int k = j; k < numAtoms; k++) {
|
|
if (Bi(j, k) > 0) {
|
|
HATSc += getHATS((double)Wc(j), (double)Wc(j), (double)H(j, j),
|
|
(double)H(j, j));
|
|
|
|
if (H(j, k) > 0) {
|
|
H0c += getH((double)Wc(j), (double)Wc(k), (double)H(j, k));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
auto Bimat = GetGeodesicMatrix(dist, i, numAtoms);
|
|
Map<MatrixXd> Bj(Bimat.data(), numAtoms, numAtoms);
|
|
if (i > 0 && i < 9) { // use Bj
|
|
for (int j = 0; j < numAtoms - 1; j++) {
|
|
for (int k = j + 1; k < numAtoms; k++) {
|
|
if (Bj(j, k) == 1) {
|
|
HATSc += getHATS((double)Wc(j), (double)Wc(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
|
|
if (H(j, k) > 0) {
|
|
H0c += getH((double)Wc(j), (double)Wc(k), (double)H(j, k));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (i >= 9) { // Totals missing part
|
|
for (int j = 0; j < numAtoms - 1; j++) {
|
|
for (int k = j + 1; k < numAtoms; k++) {
|
|
if (Bj(j, k) == 1) {
|
|
HATSct += 2 * getHATS((double)Wc(j), (double)Wc(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
|
|
if (H(j, k) > 0) {
|
|
H0ct += 2 * getH((double)Wc(j), (double)Wc(k), (double)H(j, k));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (i < 9) {
|
|
HATSk[i] = HATSc;
|
|
Hk[i] = H0c;
|
|
}
|
|
|
|
R0c = 0.0;
|
|
Rkmaxc = 0.0;
|
|
|
|
// from 1 to 8
|
|
if (i > 0 && i < 9) {
|
|
for (int j = 0; j < numAtoms - 1; j++) {
|
|
for (int k = j + 1; k < numAtoms; k++) {
|
|
if (Bj(j, k) == 1) {
|
|
tmpc = getH((double)Wc(j), (double)Wc(k),
|
|
(double)R(j, k)); // Use same function but on all R not
|
|
// "H>0" like in the previous loop &
|
|
// i>0!
|
|
|
|
R0c += tmpc;
|
|
|
|
if (tmpc > Rkmaxc) {
|
|
Rkmaxc = tmpc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Rk[i - 1] = R0c;
|
|
Rp[i - 1] = Rkmaxc;
|
|
}
|
|
|
|
if (i >= 9) {
|
|
for (int j = 0; j < numAtoms - 1; j++) {
|
|
for (int k = j + 1; k < numAtoms; k++) {
|
|
if (Bj(j, k) == 1) {
|
|
R0ct += 2 * getH((double)Wc(j), (double)Wc(k),
|
|
(double)R(j, k)); // Use same function but on all
|
|
// R not "H>0" like in the
|
|
// previous loop & i>0!
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// can be column vs row selected that can explain the issue!
|
|
double HATSTc = HATSk[0] + HATSct;
|
|
for (int ii = 1; ii < 9; ii++) {
|
|
HATSTc += 2 * HATSk[ii];
|
|
}
|
|
|
|
double HTc = Hk[0] + H0ct;
|
|
for (int ii = 1; ii < 9; ii++) {
|
|
HTc += 2.0 * Hk[ii];
|
|
}
|
|
|
|
double RTc = 0.0;
|
|
for (double rk_ii : Rk) {
|
|
RTc += 2.0 * rk_ii;
|
|
}
|
|
|
|
double RTMc = getMax(Rp);
|
|
|
|
// create the output vector...
|
|
for (int i = 0; i < 9; i++) {
|
|
res[i + 4] = roundn(Hk[i], 3);
|
|
res[i + 14] = roundn(HATSk[i], 3);
|
|
}
|
|
|
|
res[13] = roundn(HTc, 3);
|
|
res[23] = roundn(HATSTc, 3);
|
|
|
|
res[24] = roundn(rcon, 3);
|
|
res[25] = roundn(RARS, 3);
|
|
res[26] = roundn(EIG(0), 3);
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
res[i + 27] = roundn(Rk[i], 3);
|
|
res[i + 36] = roundn(Rp[i], 3);
|
|
}
|
|
|
|
res[35] = roundn(RTc + R0ct, 3);
|
|
res[44] = roundn(RTMc, 3);
|
|
}
|
|
|
|
void getGETAWAYDesc(MatrixXd H, MatrixXd R, MatrixXd Adj, int numAtoms,
|
|
const std::vector<int> &Heavylist, const ROMol &mol,
|
|
std::vector<double> &res, unsigned int precision) {
|
|
// prepare data for Getaway parameter computation
|
|
// compute parameters
|
|
|
|
VectorXd Lev = H.diagonal();
|
|
std::vector<double> heavyLev;
|
|
|
|
for (int i = 0; i < numAtoms; i++) {
|
|
if (Heavylist[i] == 1) {
|
|
heavyLev.push_back(round_to_n_digits_(Lev(i), precision));
|
|
}
|
|
}
|
|
|
|
std::vector<double> Clus = clusterArray2(heavyLev, precision);
|
|
|
|
double numHeavy = heavyLev.size();
|
|
double ITH0 = numHeavy * log(numHeavy) / log(2.0);
|
|
double ITH = ITH0;
|
|
for (double Clu : Clus) {
|
|
ITH -= Clu * log(Clu) / log(2.0);
|
|
}
|
|
res[0] = roundn(ITH, 3); // issue sometime with this due to cluster
|
|
double ISH = ITH / ITH0;
|
|
res[1] = roundn(ISH, 3); // issue sometime with this due to cluster
|
|
|
|
// use the PBF to determine 2D vs 3D (with Threshold)
|
|
// determine if this is a plane molecule
|
|
double pbf = RDKit::Descriptors::PBF(mol);
|
|
double D;
|
|
if (pbf < 1.e-5) {
|
|
D = 2.0;
|
|
} else {
|
|
D = 3.0;
|
|
}
|
|
|
|
// what about linear molecule ie (D=1) ?
|
|
double HIC = 0.0;
|
|
for (int i = 0; i < numAtoms; i++) {
|
|
HIC -= H(i, i) / D * log(H(i, i) / D) / log(2.);
|
|
}
|
|
res[2] = roundn(HIC, 3);
|
|
|
|
double HGM = 1.0;
|
|
for (int i = 0; i < numAtoms; i++) {
|
|
HGM = HGM * H(i, i);
|
|
}
|
|
HGM = 100.0 * pow(HGM, 1.0 / numAtoms);
|
|
res[3] = roundn(HGM, 3);
|
|
|
|
double RARS = R.rowwise().sum().sum() / numAtoms;
|
|
|
|
JacobiSVD<MatrixXd> mysvd = getSVD(R);
|
|
|
|
VectorXd EIG = mysvd.singularValues();
|
|
|
|
double rcon = getRCON(R, std::move(Adj), numAtoms);
|
|
|
|
std::vector<double> wp = moldata3D.GetRelativePol(mol);
|
|
|
|
VectorXd Wp = getEigenVect(wp);
|
|
|
|
std::vector<double> wm = moldata3D.GetRelativeMW(mol);
|
|
|
|
VectorXd Wm = getEigenVect(wm);
|
|
|
|
std::vector<double> wi = moldata3D.GetRelativeIonPol(mol);
|
|
|
|
VectorXd Wi = getEigenVect(wi);
|
|
|
|
std::vector<double> wv = moldata3D.GetRelativeVdW(mol);
|
|
|
|
VectorXd Wv = getEigenVect(wv);
|
|
|
|
std::vector<double> we = moldata3D.GetRelativeENeg(mol);
|
|
|
|
VectorXd We = getEigenVect(we);
|
|
|
|
std::vector<double> wu = moldata3D.GetUn(numAtoms);
|
|
|
|
VectorXd Wu = getEigenVect(wu);
|
|
|
|
std::vector<double> ws = moldata3D.GetIState(mol);
|
|
|
|
VectorXd Ws = getEigenVect(ws);
|
|
|
|
MatrixXd Bi;
|
|
MatrixXd RBw;
|
|
double HATSu, HATSm, HATSv, HATSe, HATSp, HATSi, HATSs;
|
|
double HATSut, HATSmt, HATSvt, HATSet, HATSpt, HATSit, HATSst;
|
|
double H0ut, H0mt, H0vt, H0et, H0pt, H0it, H0st;
|
|
double R0ut, R0mt, R0vt, R0et, R0pt, R0it, R0st;
|
|
double H0u, H0m, H0v, H0e, H0p, H0i, H0s;
|
|
double R0u, R0m, R0v, R0e, R0p, R0i, R0s;
|
|
double Rkmaxu, Rkmaxm, Rkmaxv, Rkmaxe, Rkmaxp, Rkmaxi, Rkmaxs;
|
|
double tmpu, tmpm, tmpv, tmpe, tmpp, tmpi, tmps;
|
|
double HATSk[7][9];
|
|
std::memset(HATSk, 0, sizeof(HATSk));
|
|
double Hk[7][9];
|
|
std::memset(Hk, 0, sizeof(Hk));
|
|
double Rk[7][8];
|
|
std::memset(Rk, 0, sizeof(Rk));
|
|
double Rp[7][8];
|
|
std::memset(Rp, 0, sizeof(Rp));
|
|
|
|
double *dist =
|
|
MolOps::getDistanceMat(mol, false); // need to be be set to false to have
|
|
// topological distance not weighted!
|
|
|
|
Map<MatrixXd> D2(dist, numAtoms, numAtoms);
|
|
|
|
double Dmax = D2.colwise().maxCoeff().maxCoeff();
|
|
|
|
HATSut = 0.0;
|
|
HATSmt = 0.0;
|
|
HATSvt = 0.0;
|
|
HATSet = 0.0;
|
|
HATSpt = 0.0;
|
|
HATSit = 0.0;
|
|
HATSst = 0.0;
|
|
|
|
H0ut = 0.0;
|
|
H0mt = 0.0;
|
|
H0vt = 0.0;
|
|
H0et = 0.0;
|
|
H0pt = 0.0;
|
|
H0it = 0.0;
|
|
H0st = 0.0;
|
|
|
|
R0ut = 0.0;
|
|
R0mt = 0.0;
|
|
R0vt = 0.0;
|
|
R0et = 0.0;
|
|
R0pt = 0.0;
|
|
R0it = 0.0;
|
|
R0st = 0.0;
|
|
|
|
// need to loop other all the D values so <= not <!
|
|
for (int i = 0; i <= Dmax; i++) {
|
|
if (i == 0) {
|
|
Bi = H.diagonal().asDiagonal();
|
|
}
|
|
|
|
HATSu = 0.0;
|
|
HATSm = 0.0;
|
|
HATSv = 0.0;
|
|
HATSe = 0.0;
|
|
HATSp = 0.0;
|
|
HATSi = 0.0;
|
|
HATSs = 0.0;
|
|
|
|
H0u = 0.0;
|
|
H0m = 0.0;
|
|
H0v = 0.0;
|
|
H0e = 0.0;
|
|
H0p = 0.0;
|
|
H0i = 0.0;
|
|
H0s = 0.0;
|
|
|
|
if (i == 0) { // use Bi
|
|
for (int j = 0; j < numAtoms; j++) {
|
|
for (int k = j; k < numAtoms; k++) {
|
|
if (Bi(j, k) > 0) {
|
|
HATSu += getHATS((double)Wu(j), (double)Wu(j), (double)H(j, j),
|
|
(double)H(j, j));
|
|
HATSm += getHATS((double)Wm(j), (double)Wm(j), (double)H(j, j),
|
|
(double)H(j, j));
|
|
HATSv += getHATS((double)Wv(j), (double)Wv(j), (double)H(j, j),
|
|
(double)H(j, j));
|
|
HATSe += getHATS((double)We(j), (double)We(j), (double)H(j, j),
|
|
(double)H(j, j));
|
|
HATSp += getHATS((double)Wp(j), (double)Wp(j), (double)H(j, j),
|
|
(double)H(j, j));
|
|
HATSi += getHATS((double)Wi(j), (double)Wi(j), (double)H(j, j),
|
|
(double)H(j, j));
|
|
HATSs += getHATS((double)Ws(j), (double)Ws(j), (double)H(j, j),
|
|
(double)H(j, j));
|
|
|
|
if (H(j, k) > 0) {
|
|
H0u += getH((double)Wu(j), (double)Wu(k), (double)H(j, k));
|
|
H0m += getH((double)Wm(j), (double)Wm(k), (double)H(j, k));
|
|
H0v += getH((double)Wv(j), (double)Wv(k), (double)H(j, k));
|
|
H0e += getH((double)We(j), (double)We(k), (double)H(j, k));
|
|
H0p += getH((double)Wp(j), (double)Wp(k), (double)H(j, k));
|
|
H0i += getH((double)Wi(j), (double)Wi(k), (double)H(j, k));
|
|
H0s += getH((double)Ws(j), (double)Ws(k), (double)H(j, k));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
auto Bimat = GetGeodesicMatrix(dist, i, numAtoms);
|
|
Map<MatrixXd> Bj(Bimat.data(), numAtoms, numAtoms);
|
|
if (i > 0 && i < 9) { // use Bj
|
|
for (int j = 0; j < numAtoms - 1; j++) {
|
|
for (int k = j + 1; k < numAtoms; k++) {
|
|
if (Bj(j, k) == 1) {
|
|
HATSu += getHATS((double)Wu(j), (double)Wu(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
HATSm += getHATS((double)Wm(j), (double)Wm(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
HATSv += getHATS((double)Wv(j), (double)Wv(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
HATSe += getHATS((double)We(j), (double)We(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
HATSp += getHATS((double)Wp(j), (double)Wp(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
HATSi += getHATS((double)Wi(j), (double)Wi(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
HATSs += getHATS((double)Ws(j), (double)Ws(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
|
|
if (H(j, k) > 0) {
|
|
H0u += getH((double)Wu(j), (double)Wu(k), (double)H(j, k));
|
|
H0m += getH((double)Wm(j), (double)Wm(k), (double)H(j, k));
|
|
H0v += getH((double)Wv(j), (double)Wv(k), (double)H(j, k));
|
|
H0e += getH((double)We(j), (double)We(k), (double)H(j, k));
|
|
H0p += getH((double)Wp(j), (double)Wp(k), (double)H(j, k));
|
|
H0i += getH((double)Wi(j), (double)Wi(k), (double)H(j, k));
|
|
H0s += getH((double)Ws(j), (double)Ws(k), (double)H(j, k));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (i >= 9) { // Totals missing part
|
|
for (int j = 0; j < numAtoms - 1; j++) {
|
|
for (int k = j + 1; k < numAtoms; k++) {
|
|
if (Bj(j, k) == 1) {
|
|
HATSut += 2 * getHATS((double)Wu(j), (double)Wu(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
HATSmt += 2 * getHATS((double)Wm(j), (double)Wm(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
HATSvt += 2 * getHATS((double)Wv(j), (double)Wv(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
HATSet += 2 * getHATS((double)We(j), (double)We(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
HATSpt += 2 * getHATS((double)Wp(j), (double)Wp(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
HATSit += 2 * getHATS((double)Wi(j), (double)Wi(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
HATSst += 2 * getHATS((double)Ws(j), (double)Ws(k), (double)H(j, j),
|
|
(double)H(k, k));
|
|
|
|
if (H(j, k) > 0) {
|
|
H0ut += 2 * getH((double)Wu(j), (double)Wu(k), (double)H(j, k));
|
|
H0mt += 2 * getH((double)Wm(j), (double)Wm(k), (double)H(j, k));
|
|
H0vt += 2 * getH((double)Wv(j), (double)Wv(k), (double)H(j, k));
|
|
H0et += 2 * getH((double)We(j), (double)We(k), (double)H(j, k));
|
|
H0pt += 2 * getH((double)Wp(j), (double)Wp(k), (double)H(j, k));
|
|
H0it += 2 * getH((double)Wi(j), (double)Wi(k), (double)H(j, k));
|
|
H0st += 2 * getH((double)Ws(j), (double)Ws(k), (double)H(j, k));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (i < 9) {
|
|
HATSk[0][i] = HATSu;
|
|
HATSk[1][i] = HATSm;
|
|
HATSk[2][i] = HATSv;
|
|
HATSk[3][i] = HATSe;
|
|
HATSk[4][i] = HATSp;
|
|
HATSk[5][i] = HATSi;
|
|
HATSk[6][i] = HATSs;
|
|
|
|
Hk[0][i] = H0u;
|
|
Hk[1][i] = H0m;
|
|
Hk[2][i] = H0v;
|
|
Hk[3][i] = H0e;
|
|
Hk[4][i] = H0p;
|
|
Hk[5][i] = H0i;
|
|
Hk[6][i] = H0s;
|
|
}
|
|
|
|
R0u = 0.0;
|
|
R0m = 0.0;
|
|
R0v = 0.0;
|
|
R0e = 0.0;
|
|
R0p = 0.0;
|
|
R0i = 0.0;
|
|
R0s = 0.0;
|
|
|
|
Rkmaxu = 0;
|
|
Rkmaxm = 0;
|
|
Rkmaxv = 0;
|
|
Rkmaxe = 0;
|
|
Rkmaxp = 0;
|
|
Rkmaxi = 0;
|
|
Rkmaxs = 0;
|
|
|
|
// from 1 to 8
|
|
if (i > 0 && i < 9) {
|
|
for (int j = 0; j < numAtoms - 1; j++) {
|
|
for (int k = j + 1; k < numAtoms; k++) {
|
|
if (Bj(j, k) == 1) {
|
|
tmpu = getH((double)Wu(j), (double)Wu(k),
|
|
(double)R(j, k)); // Use same function but on all R not
|
|
// "H>0" like in the previous loop &
|
|
// i>0!
|
|
tmpm = getH((double)Wm(j), (double)Wm(k),
|
|
(double)R(j, k)); // Use same function but on all R not
|
|
// "H>0" like in the previous loop &
|
|
// i>0!
|
|
tmpv = getH((double)Wv(j), (double)Wv(k),
|
|
(double)R(j, k)); // Use same function but on all R not
|
|
// "H>0" like in the previous loop &
|
|
// i>0!
|
|
tmpe = getH((double)We(j), (double)We(k),
|
|
(double)R(j, k)); // Use same function but on all R not
|
|
// "H>0" like in the previous loop &
|
|
// i>0!
|
|
tmpp = getH((double)Wp(j), (double)Wp(k),
|
|
(double)R(j, k)); // Use same function but on all R not
|
|
// "H>0" like in the previous loop &
|
|
// i>0!
|
|
tmpi = getH((double)Wi(j), (double)Wi(k),
|
|
(double)R(j, k)); // Use same function but on all R not
|
|
// "H>0" like in the previous loop &
|
|
// i>0!
|
|
tmps = getH((double)Ws(j), (double)Ws(k),
|
|
(double)R(j, k)); // Use same function but on all R not
|
|
// "H>0" like in the previous loop &
|
|
// i>0!
|
|
R0u += tmpu;
|
|
R0m += tmpm;
|
|
R0v += tmpv;
|
|
R0e += tmpe;
|
|
R0p += tmpp;
|
|
R0i += tmpi;
|
|
R0s += tmps;
|
|
if (tmpu > Rkmaxu) {
|
|
Rkmaxu = tmpu;
|
|
}
|
|
if (tmpm > Rkmaxm) {
|
|
Rkmaxm = tmpm;
|
|
}
|
|
if (tmpv > Rkmaxv) {
|
|
Rkmaxv = tmpv;
|
|
}
|
|
if (tmpe > Rkmaxe) {
|
|
Rkmaxe = tmpe;
|
|
}
|
|
if (tmpp > Rkmaxp) {
|
|
Rkmaxp = tmpp;
|
|
}
|
|
if (tmpi > Rkmaxi) {
|
|
Rkmaxi = tmpi;
|
|
}
|
|
if (tmps > Rkmaxs) {
|
|
Rkmaxs = tmps;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Rk[0][i - 1] = R0u;
|
|
Rk[1][i - 1] = R0m;
|
|
Rk[2][i - 1] = R0v;
|
|
Rk[3][i - 1] = R0e;
|
|
Rk[4][i - 1] = R0p;
|
|
Rk[5][i - 1] = R0i;
|
|
Rk[6][i - 1] = R0s;
|
|
|
|
Rp[0][i - 1] = Rkmaxu;
|
|
Rp[1][i - 1] = Rkmaxm;
|
|
Rp[2][i - 1] = Rkmaxv;
|
|
Rp[3][i - 1] = Rkmaxe;
|
|
Rp[4][i - 1] = Rkmaxp;
|
|
Rp[5][i - 1] = Rkmaxi;
|
|
Rp[6][i - 1] = Rkmaxs;
|
|
}
|
|
|
|
if (i >= 9) {
|
|
for (int j = 0; j < numAtoms - 1; j++) {
|
|
for (int k = j + 1; k < numAtoms; k++) {
|
|
if (Bj(j, k) == 1) {
|
|
R0ut += 2 * getH((double)Wu(j), (double)Wu(k),
|
|
(double)R(j, k)); // Use same function but on all
|
|
// R not "H>0" like in the
|
|
// previous loop & i>0!
|
|
R0mt += 2 * getH((double)Wm(j), (double)Wm(k),
|
|
(double)R(j, k)); // Use same function but on all
|
|
// R not "H>0" like in the
|
|
// previous loop & i>0!
|
|
R0vt += 2 * getH((double)Wv(j), (double)Wv(k),
|
|
(double)R(j, k)); // Use same function but on all
|
|
// R not "H>0" like in the
|
|
// previous loop & i>0!
|
|
R0et += 2 * getH((double)We(j), (double)We(k),
|
|
(double)R(j, k)); // Use same function but on all
|
|
// R not "H>0" like in the
|
|
// previous loop & i>0!
|
|
R0pt += 2 * getH((double)Wp(j), (double)Wp(k),
|
|
(double)R(j, k)); // Use same function but on all
|
|
// R not "H>0" like in the
|
|
// previous loop & i>0!
|
|
R0it += 2 * getH((double)Wi(j), (double)Wi(k),
|
|
(double)R(j, k)); // Use same function but on all
|
|
// R not "H>0" like in the
|
|
// previous loop & i>0!
|
|
R0st += 2 * getH((double)Ws(j), (double)Ws(k),
|
|
(double)R(j, k)); // Use same function but on all
|
|
// R not "H>0" like in the
|
|
// previous loop & i>0!
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// can be column vs row selected that can explain the issue!
|
|
double HATSTu = HATSk[0][0] + HATSut;
|
|
double HATSTm = HATSk[1][0] + HATSmt;
|
|
double HATSTv = HATSk[2][0] + HATSvt;
|
|
double HATSTe = HATSk[3][0] + HATSet;
|
|
double HATSTp = HATSk[4][0] + HATSpt;
|
|
double HATSTi = HATSk[5][0] + HATSit;
|
|
double HATSTs = HATSk[6][0] + HATSst;
|
|
|
|
for (int ii = 1; ii < 9; ii++) {
|
|
HATSTu += 2 * HATSk[0][ii];
|
|
HATSTm += 2 * HATSk[1][ii];
|
|
HATSTv += 2 * HATSk[2][ii];
|
|
HATSTe += 2 * HATSk[3][ii];
|
|
HATSTp += 2 * HATSk[4][ii];
|
|
HATSTi += 2 * HATSk[5][ii];
|
|
HATSTs += 2 * HATSk[6][ii];
|
|
}
|
|
|
|
double HTu = Hk[0][0] + H0ut;
|
|
double HTm = Hk[1][0] + H0mt;
|
|
double HTv = Hk[2][0] + H0vt;
|
|
double HTe = Hk[3][0] + H0et;
|
|
double HTp = Hk[4][0] + H0pt;
|
|
double HTi = Hk[5][0] + H0it;
|
|
double HTs = Hk[6][0] + H0st;
|
|
|
|
for (int ii = 1; ii < 9; ii++) {
|
|
HTu += 2.0 * Hk[0][ii];
|
|
HTm += 2.0 * Hk[1][ii];
|
|
HTv += 2.0 * Hk[2][ii];
|
|
HTe += 2.0 * Hk[3][ii];
|
|
HTp += 2.0 * Hk[4][ii];
|
|
HTi += 2.0 * Hk[5][ii];
|
|
HTs += 2.0 * Hk[6][ii];
|
|
}
|
|
|
|
// 2*(Rk[1]+Rk[2]+Rk[3]+Rk[4]+Rk[5]+Rk[6]+Rk[7]+Rk[8]) // this is not true
|
|
// this is on all the element
|
|
|
|
double RTu = 0.0;
|
|
double RTm = 0.0;
|
|
double RTv = 0.0;
|
|
double RTe = 0.0;
|
|
double RTp = 0.0;
|
|
double RTi = 0.0;
|
|
double RTs = 0.0;
|
|
|
|
for (int ii = 0; ii < 8; ii++) {
|
|
RTu += 2.0 * Rk[0][ii];
|
|
RTm += 2.0 * Rk[1][ii];
|
|
RTv += 2.0 * Rk[2][ii];
|
|
RTe += 2.0 * Rk[3][ii];
|
|
RTp += 2.0 * Rk[4][ii];
|
|
RTi += 2.0 * Rk[5][ii];
|
|
RTs += 2.0 * Rk[6][ii];
|
|
}
|
|
|
|
double RTMu = getMax(Rp[0]);
|
|
double RTMm = getMax(Rp[1]);
|
|
double RTMv = getMax(Rp[2]);
|
|
double RTMe = getMax(Rp[3]);
|
|
double RTMp = getMax(Rp[4]);
|
|
double RTMi = getMax(Rp[5]);
|
|
double RTMs = getMax(Rp[6]);
|
|
|
|
// create the output vector...
|
|
for (int i = 0; i < 9; i++) {
|
|
res[i + 4] = roundn(Hk[0][i], 3);
|
|
res[i + 14] = roundn(HATSk[0][i], 3);
|
|
res[i + 24] = roundn(Hk[1][i], 3);
|
|
res[i + 34] = roundn(HATSk[1][i], 3);
|
|
res[i + 44] = roundn(Hk[2][i], 3);
|
|
res[i + 54] = roundn(HATSk[2][i], 3);
|
|
res[i + 64] = roundn(Hk[3][i], 3);
|
|
res[i + 74] = roundn(HATSk[3][i], 3);
|
|
res[i + 84] = roundn(Hk[4][i], 3);
|
|
res[i + 94] = roundn(HATSk[4][i], 3);
|
|
res[i + 104] = roundn(Hk[5][i], 3);
|
|
res[i + 114] = roundn(HATSk[5][i], 3);
|
|
res[i + 124] = roundn(Hk[6][i], 3);
|
|
res[i + 134] = roundn(HATSk[6][i], 3);
|
|
}
|
|
|
|
res[13] = roundn(HTu, 3);
|
|
res[23] = roundn(HATSTu, 3);
|
|
res[33] = roundn(HTm, 3);
|
|
res[43] = roundn(HATSTm, 3);
|
|
res[53] = roundn(HTv, 3);
|
|
res[63] = roundn(HATSTv, 3);
|
|
res[73] = roundn(HTe, 3);
|
|
res[83] = roundn(HATSTe, 3);
|
|
res[93] = roundn(HTp, 3);
|
|
res[103] = roundn(HATSTp, 3);
|
|
res[113] = roundn(HTi, 3);
|
|
res[123] = roundn(HATSTi, 3);
|
|
res[133] = roundn(HTs, 3);
|
|
res[143] = roundn(HATSTs, 3);
|
|
|
|
res[144] = roundn(rcon, 3);
|
|
res[145] = roundn(RARS, 3);
|
|
res[146] = roundn(EIG(0), 3);
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
res[i + 147] = roundn(Rk[0][i], 3);
|
|
res[i + 156] = roundn(Rp[0][i], 3);
|
|
res[i + 165] = roundn(Rk[1][i], 3);
|
|
res[i + 174] = roundn(Rp[1][i], 3);
|
|
res[i + 183] = roundn(Rk[2][i], 3);
|
|
res[i + 192] = roundn(Rp[2][i], 3);
|
|
res[i + 201] = roundn(Rk[3][i], 3);
|
|
res[i + 210] = roundn(Rp[3][i], 3);
|
|
res[i + 219] = roundn(Rk[4][i], 3);
|
|
res[i + 228] = roundn(Rp[4][i], 3);
|
|
res[i + 237] = roundn(Rk[5][i], 3);
|
|
res[i + 246] = roundn(Rp[5][i], 3);
|
|
res[i + 255] = roundn(Rk[6][i], 3);
|
|
res[i + 264] = roundn(Rp[6][i], 3);
|
|
}
|
|
|
|
res[155] = roundn(RTu + R0ut, 3);
|
|
res[164] = roundn(RTMu, 3);
|
|
res[173] = roundn(RTm + R0mt, 3);
|
|
res[182] = roundn(RTMm, 3);
|
|
res[191] = roundn(RTv + R0vt, 3);
|
|
res[200] = roundn(RTMv, 3);
|
|
res[209] = roundn(RTe + R0et, 3);
|
|
res[218] = roundn(RTMe, 3);
|
|
res[227] = roundn(RTp + R0pt, 3);
|
|
res[236] = roundn(RTMp, 3);
|
|
res[245] = roundn(RTi + R0it, 3);
|
|
res[254] = roundn(RTMi, 3);
|
|
res[263] = roundn(RTs + R0st, 3);
|
|
res[272] = roundn(RTMs, 3);
|
|
}
|
|
|
|
/*
|
|
std::vector<std::string>
|
|
GETAWAYNAMES={"ITH","ISH","HIC","HGM","H0u","H1u","H2u","H3u","H4u","H5u","H6u","H7u","H8u","HTu",
|
|
"HATS0u","HATS1u","HATS2u","HATS3u","HATS4u","HATS5u","HATS6u","HATS7u","HATS8u","HATSu","H0m","H1m","H2m","H3m","H4m","H5m",
|
|
"H6m","H7m","H8m","HTm","HATS0m","HATS1m","HATS2m","HATS3m","HATS4m","HATS5m","HATS6m","HATS7m","HATS8m","HATSm","H0v","H1v",
|
|
"H2v","H3v","H4v","H5v","H6v","H7v","H8v","HTv","HATS0v","HATS1v","HATS2v","HATS3v","HATS4v","HATS5v","HATS6v","HATS7v","HATS8v",
|
|
"HATSv","H0e","H1e","H2e","H3e","H4e","H5e","H6e","H7e","H8e","HTe","HATS0e","HATS1e","HATS2e","HATS3e","HATS4e","HATS5e","HATS6e",
|
|
"HATS7e","HATS8e","HATSe","H0p","H1p","H2p","H3p","H4p","H5p","H6p","H7p","H8p","HTp","HATS0p","HATS1p","HATS2p","HATS3p","HATS4p",
|
|
"HATS5p","HATS6p","HATS7p","HATS8p","HATSp","H0i","H1i","H2i","H3i","H4i","H5i","H6i","H7i","H8i","HTi","HATS0i","HATS1i","HATS2i",
|
|
"HATS3i","HATS4i","HATS5i","HATS6i","HATS7i","HATS8i","HATSi","H0s","H1s","H2s","H3s","H4s","H5s","H6s","H7s","H8s","HTs","HATS0s",
|
|
"HATS1s","HATS2s","HATS3s","HATS4s","HATS5s","HATS6s","HATS7s","HATS8s","HATSs","RCON","RARS","REIG","R1u","R2u","R3u","R4u","R5u",
|
|
"R6u","R7u","R8u","RTu","R1u+","R2u+","R3u+","R4u+","R5u+","R6u+","R7u+","R8u+","RTu+","R1m","R2m","R3m","R4m","R5m","R6m","R7m",
|
|
"R8m","RTm","R1m+","R2m+","R3m+","R4m+","R5m+","R6m+","R7m+","R8m+","RTm+","R1v","R2v","R3v","R4v","R5v","R6v","R7v","R8v","RTv",
|
|
"R1v+","R2v+","R3v+","R4v+","R5v+","R6v+","R7v+","R8v+","RTv+","R1e","R2e","R3e","R4e","R5e","R6e","R7e","R8e","RTe","R1e+","R2e+",
|
|
"R3e+","R4e+","R5e+","R6e+","R7e+","R8e+","RTe+","R1p","R2p","R3p","R4p","R5p","R6p","R7p","R8p","RTp","R1p+","R2p+","R3p+","R4p+",
|
|
"R5p+","R6p+","R7p+","R8p+","RTp+","R1i","R2i","R3i","R4i","R5i","R6i","R7i","R8i","RTi","R1i+","R2i+","R3i+","R4i+","R5i+","R6i+",
|
|
"R7i+","R8i+","RTi+","R1s","R2s","R3s","R4s","R5s","R6s","R7s","R8s","RTs","R1s+","R2s+","R3s+","R4s+","R5s+","R6s+","R7s+","R8s+","RTs+"};
|
|
*/
|
|
|
|
void GetGETAWAYone(double *dist3D, double *AdjMat, std::vector<double> Vpoints,
|
|
const ROMol &mol, const Conformer &conf,
|
|
const std::vector<int> &Heavylist, std::vector<double> &res,
|
|
unsigned int precision,
|
|
const std::string &customAtomPropName) {
|
|
PRECONDITION(dist3D != nullptr, "no distance matrix");
|
|
PRECONDITION(AdjMat != nullptr, "no adjacency matrix");
|
|
int numAtoms = conf.getNumAtoms();
|
|
|
|
Map<MatrixXd> ADJ(AdjMat, numAtoms, numAtoms);
|
|
|
|
Map<MatrixXd> DM(dist3D, numAtoms, numAtoms);
|
|
|
|
double *vpoints = &Vpoints[0];
|
|
|
|
Map<MatrixXd> matorigin(vpoints, 3, numAtoms);
|
|
|
|
MatrixXd MatOrigin = matorigin.transpose();
|
|
|
|
MatrixXd Xmean = GetCenterMatrix(MatOrigin);
|
|
|
|
MatrixXd H = GetHmatrix(Xmean);
|
|
|
|
MatrixXd R = GetRmatrix(H, DM, numAtoms);
|
|
|
|
getGETAWAYDescCustom(H, R, ADJ, numAtoms, Heavylist, mol, res, precision,
|
|
customAtomPropName);
|
|
}
|
|
|
|
void GetGETAWAY(double *dist3D, double *AdjMat, std::vector<double> Vpoints,
|
|
const ROMol &mol, const Conformer &conf,
|
|
std::vector<int> Heavylist, std::vector<double> &res,
|
|
unsigned int precision) {
|
|
PRECONDITION(dist3D != nullptr, "no distance matrix");
|
|
PRECONDITION(AdjMat != nullptr, "no adjacency matrix");
|
|
|
|
int numAtoms = conf.getNumAtoms();
|
|
|
|
Map<MatrixXd> ADJ(AdjMat, numAtoms, numAtoms);
|
|
|
|
Map<MatrixXd> DM(dist3D, numAtoms, numAtoms);
|
|
|
|
double *vpoints = &Vpoints[0];
|
|
|
|
Map<MatrixXd> matorigin(vpoints, 3, numAtoms);
|
|
|
|
MatrixXd MatOrigin = matorigin.transpose();
|
|
|
|
MatrixXd Xmean = GetCenterMatrix(MatOrigin);
|
|
|
|
MatrixXd H = GetHmatrix(Xmean);
|
|
|
|
MatrixXd R = GetRmatrix(H, DM, numAtoms);
|
|
|
|
getGETAWAYDesc(H, R, ADJ, numAtoms, Heavylist, mol, res, precision);
|
|
}
|
|
|
|
} // end of anonymous namespace
|
|
|
|
void GETAWAY(const ROMol &mol, std::vector<double> &res, int confId,
|
|
unsigned int precision, const std::string &customAtomPropName) {
|
|
PRECONDITION(mol.getNumConformers() >= 1, "molecule has no conformers")
|
|
|
|
int numAtoms = mol.getNumAtoms();
|
|
|
|
const Conformer &conf = mol.getConformer(confId);
|
|
|
|
std::vector<double> Vpoints(3 * numAtoms);
|
|
|
|
for (int i = 0; i < numAtoms; ++i) {
|
|
Vpoints[3 * i] = conf.getAtomPos(i).x;
|
|
Vpoints[3 * i + 1] = conf.getAtomPos(i).y;
|
|
Vpoints[3 * i + 2] = conf.getAtomPos(i).z;
|
|
}
|
|
|
|
std::vector<int> Heavylist = GetHeavyList(mol);
|
|
// should be the same as the List size upper!
|
|
// int nHeavyAt= mol.getNumHeavyAtoms();
|
|
|
|
double *dist3D = MolOps::get3DDistanceMat(mol, confId);
|
|
|
|
double *AdjMat = MolOps::getAdjacencyMatrix(
|
|
mol, false, 0, false,
|
|
nullptr); // false to have only the 1,0 matrix unweighted
|
|
|
|
if (!customAtomPropName.empty()) {
|
|
res.clear();
|
|
res.resize(45);
|
|
GetGETAWAYone(dist3D, AdjMat, Vpoints, mol, conf, Heavylist, res, precision,
|
|
customAtomPropName);
|
|
} else {
|
|
res.clear();
|
|
res.resize(273);
|
|
|
|
GetGETAWAY(dist3D, AdjMat, Vpoints, mol, conf, Heavylist, res, precision);
|
|
}
|
|
}
|
|
|
|
} // namespace Descriptors
|
|
} // namespace RDKit
|